#Loading packages and data
library(readtext)
library(quanteda)
library(stm)
library(dplyr)
library(stringr)
library(ggplot2)

We collected data on regional innovation programs for the following EU member states (Czech Republic, Germany, Poland, Portugal, and UK). Regional programs are available for two time periods: before and after introduction of conditionality in 2013.

Here we look at regional programs, usually drafted by NUTS2 level authorities, and not more general state programs. The exception is Czech Republic that consists of NUTS1 regions only.

We perform analysis by country, starting with Germany below.

Data

Reading in data. These are PDFs of regional innovation programs that have been converted into plain text and then translated into English using EC JRC software.

DATA_DIR <- "~/Dropbox/Research/EC JRC project/Data/English texts/" 
ec_files <- readtext(paste0(DATA_DIR, "/*"), 
                                 docvarsfrom = "filenames", 
                                 dvsep="_", 
                                 docvarnames = c("RCode", "Region", "Year", "Lang"))
ec_files$condition <- as.numeric(ec_files$Year > 2013)
ec_files$Country <- word(row.names(ec_files), 1, sep = fixed('/'))
ec_corpus <- corpus(ec_files, text_field = "text") 
#subset of corpus per country, as automated translation is imperfect 
#and picking up language specific topis 
#so estimation is done country by country
de_corpus <- corpus_subset(ec_corpus, Country=="Germany")
pl_corpus <- corpus_subset(ec_corpus, Country=="Poland")
pt_corpus <- corpus_subset(ec_corpus, Country=="Portugal")
cz_corpus <- corpus_subset(ec_corpus, Country=="Czech Republic")

Germany

Tokenizing documents.

#tokenizing
tok <- tokens(de_corpus, what = "word",
              removePunct = TRUE,
              removeSymbols = TRUE,
              removeNumbers = TRUE,
              removeTwitter = TRUE,
              removeURL = TRUE,
              removeHyphens = TRUE,
              verbose = TRUE)
Starting tokenization...
...tokenizing 1 of 1 blocks...
, removing URLs...hashing tokens
...total elapsed:  0.741 seconds.
Finished tokenizing and cleaning 36 texts.

Creating document feature matrix.

dfm <- dfm(tok, 
           tolower = TRUE,
           remove= c(stopwords("SMART"), "melt", "hessen", "hamburg", "schleswig", "holstein",
                     "bavaria", "bavarian", "berlin", "bremen", "saxoni", "northrhine", "westphalia",
                     "rhineland", "saarland", "mecklenburg", "wÿrttemberg", "baden", "anhalt",
                     "chsischen", "chsisch", "pomorski", "zachodniopomorski", "kujawsko", "łódź",
                     "podkarpacki", "mazovia", "mazowiecki", "pomerania", "świętokrzyski", "podlaski",
                     "warmia", "lubuski", "malopolska", "małopolsk", "wielkopolska", "sląskie",
                     "działao", "mazuri", "olsztyn", "łódzkie", "mazurskiego", "góra", "silesian",
                     "warsaw", "rzeszów", "mazowsz", "mazowieckich", "małopolska", "małopolski",
                     "śląskie", "kraków", "alentejo", "tejo", "lisboa", "azor", "algarv", "czech",
                     "republ", "tejo", "sociedad", "madeira", "lisbon", "saxoni", "bavaria", "sachsen"),
           stem=TRUE, 
           verbose = TRUE)
Creating a dfm from a tokens object ...
   ... lowercasing
   ... found 36 documents, 56,220 features
   ... removed 490 features, from 632 supplied (glob) feature types
   ... stemming features (English), trimmed 6493 feature variants
   ... created a 36 x 49,237 sparse dfm
   ... complete. 
Elapsed time: 0.822 seconds.
#Removing any digits. `dfm` picks up any separated digits, not digits that are part of tokens.
dfm.m <- dfm_select(dfm, '[\\d-]',  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 2,875 features, from 1 supplied (regex) feature types
#Removing any punctuation. `dfm` picks up any punctuation unless it's part of a token.
dfm.m <- dfm_select(dfm.m, "[[:punct:]]",  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 1,042 features, from 1 supplied (regex) feature types
#Removing any tokens less than four characters.
dfm.m <- dfm_select(dfm.m, '^.{1,3}$',  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 1,963 features, from 1 supplied (regex) feature types
#Dropping words that appear less than 10 times and in less than 5 documents.
dfm.trim <- dfm_trim(dfm.m, min_count = 10, min_docfreq = 5)
Removing features occurring: 
  - fewer than 10 times: 39,146
  - in fewer than 5 documents: 38,753
  Total features removed: 39,762 (91.7%).
topfeatures(dfm.trim, n = 50)
    innov   develop  research    region technolog     close  strategi  industri      area 
     8149      7130      6206      4699      4694      2894      2836      2608      2506 
  support  programm  institut    import   project   network   cluster    sector    energi 
     2483      2414      2374      2328      2323      2281      2225      2221      2194 
   object   product      high      busi    econom   compani    scienc    cooper   increas 
     2162      2048      2016      2004      1987      1919      1918      1899      1898 
  countri   economi      work   discuss  knowledg    servic    market   univers     field 
     1896      1889      1872      1858      1736      1691      1668      1619      1611 
   involv  competit  structur   process   potenti      fund  unterstu    polici implement 
     1603      1592      1588      1572      1566      1564      1501      1483      1474 
  germani    employ      educ    result      oper 
     1465      1427      1423      1413      1410 
sparsity(dfm.trim)
[1] 0.5655617
nfeature(dfm.trim)
[1] 3595

Converting DFM into format for STM package

stm.dfm <- convert(dfm.trim, to = "stm",  docvars = docvars(de_corpus))

Analysis

In the analysis we consider the effect of introducing conditionality on the content of innovation programs. In order to achieve that we implement a structural topic model (Roberts et al., 2015). We model topic prevalence in the context of the conditionality condition marking programs before and after 2013. In addition, we control for region fixed effects. The aim is to allow the observed metadata to affect the frequency with which a topic is discussed in innovation programs. This allows us to test the degree of association between conditionality (and region effects) and the average proportion of a document discussing a topic.

Searching for optimal number of topics

We assess the optimal number of topics that need to specified for the STM analysis. We follow original STM paper and focus on exclusivity and semantic coherence measures. Mimno et al. (2011) propose semantic coherence measure, closely related to point-wise mutual information measure proposed by Newman et al. (2010) to evaluate topic quality. Mimno et al. (2011) show that semantic coherence corresponds to expert judgments and more general human judgments in Amazon’s Mechanical Turk experiments.

Exclusivity score for each topic follows Bischof and Airoldi (2012). Highly frequent words in a given topic that don’t appear too often in other topics are said to make that topic exclusive. Cohesive and exclusive topics are more semantically useful. Following Roberts et al. (2015) we generate a set of candidate models ranging between 3 and 50 topics.

We then plot the exclusivity and semantic coherence (numbers closer to zero indicate higher coherence), and select a model on the semantic coherence-exclusivity “frontier”, that is, where no model strictly dominates another in terms of semantic coherence and exclusivity.

#pdf("search.pdf")
par(mar=c(5,4,4,5)+.1)
plot(search$results$K,search$results$exclus,type="l",col="red", 
     xlab="Number of topics", ylab="Exclusivity")
axis(side=1,at=seq(0,50,5))
#abline(v=c(5,10), col="green")
par(new=TRUE)
plot(search$results$K, search$results$semcoh,
     type="l",col="blue",xaxt="n",yaxt="n",xlab="",ylab="")
axis(4)
mtext("Semantic Coherence",side=4,line=3)
legend("right",col=c("red","blue"),lty=1,legend=c("excl","sem coh"))

#dev.off()

We select the model with 7 topics for our analysis – there’s a drop in semantic coherence after \(k=7\). We estimate the model with conditionality and region covariates.

Exploring words associated with each topic.

One way to summarize topics is to combine term frequency and exclusivity to that topic into a univariate summary statistic. In STM package this is implemented as FREX following Bischof and Airoldi (2012) and Airoldi and Bischof (2016). The logic behind this measure is that both frequency and exclusivity are important factors in determining semantic content of a word and form a two dimensional summary of topical content. FREX is the geometric average of frequency and exclusivity and can be viewed as a univariate measure of topical importance. STM authors suggest that nonexclusive words are less likely to carry topic-specific content, while infrequent words occur too rarely to form the semantic core of a topic. FREX is therefore combining information from the most frequent words in the corpus that are also likely to have been generated from the topic of interest to summarize its content. In practice, topic quality is are usually evaluated by highest probability words.

Here, we look both at FREX and highest probability words.

labelTopics(topics7)
Topic 1 Top Words:
     Highest Prob: research, innov, develop, technolog, industri, work, institut 
     FREX: contract, cent, parti, contractor, academ, kšnnen, brandenburg 
     Lift: hšlfte, schÿler, kreativitšt, studiengšng, contractor, klaus, studiengšngen 
     Score: hšlfte, ÿber, kšnnen, mÿssen, fšrderung, universitšt, mobilitšt 
Topic 2 Top Words:
     Highest Prob: innov, research, develop, technolog, region, cluster, close 
     FREX: universita, maritim, schlu, octob, western, ndischen, juli 
     Lift: sselfunkt, masterpla, nstlich, hochschulischen, fteentwicklung, ndigt, innovationsunterstu 
     Score: sselfunkt, unterstu, universita, schlu, rken, fachkra, wertscho 
Topic 3 Top Words:
     Highest Prob: assess, instrument, task, import, technolog, network, unterstu 
     FREX: satisfi, reserv, nanotech, assess, input, benchmark, instrument 
     Lift: satisfi, umwelttech, nanotech, satisfact, reserv, instru, origina 
     Score: satisfi, unterstu, bergeordneten, umwelttech, nanotech, stribut, dafu 
Topic 4 Top Words:
     Highest Prob: develop, region, citi, programm, area, object, project 
     FREX: citi, ršumlich, port, wettbewerbsfšhigkeit, urban, beschšftigung, flšchen 
     Lift: flšchen, ršumlich, stšdte, stšdtischen, stšdten, prioritšt, residenti 
     Score: flšchen, ÿber, fšrderung, wettbewerbsfšhigkeit, ršumlich, beschšftigung, kšnnen 
Topic 5 Top Words:
     Highest Prob: innov, research, develop, technolog, region, strategi, institut 
     FREX: lower, saxoni, frankfurt, smart, projekt, nchen, darmstadt 
     Lift: spain, ernšhrungswirtschaft, schlÿsseltechnologien, komplementšr, fÿhrender, forschungsfšrderung, ausgrÿndungen 
     Score: spain, ÿber, fšrderung, kšnnen, stšrken, universitšt, stšrkung 
Topic 6 Top Words:
     Highest Prob: region, develop, programm, support, innov, oper, close 
     FREX: priorita, tsachs, ftigung, wettbewerbsfa, erdf, koha, tourism 
     Lift: auftra, verwaltungsbeho, rderbedarf, tsachs, dtischen, ndlicher, rderfa 
     Score: auftra, priorita, tsachs, wettbewerbsfa, ftigung, unterstu, bevo 
Topic 7 Top Words:
     Highest Prob: innov, research, develop, strategi, technolog, product, close 
     FREX: chsisch, mobilita, struggl, ment, document, saxoni, wertscho 
     Lift: niedersa, chsisch, tskonzept, passfa, struggl, strategisch, copi 
     Score: niedersa, unterstu, chsisch, mobilita, struggl, fachkra, rken 

Plotting the same:

plot(topics7,type="labels", n = 15, text.cex = .6)

Graphical display of estimated topic proportions

Here we have expected proportions of the corpus that belongs to each topic.

plot(topics7,type="summary", xlim = c(0, 1), n = 10, text.cex = .5)

Topical perspectives

Topics 5 and 7 appear to have very similar top words. We can plot the contrast in words across these two topics. This plot calculates the difference in probability of a word for the two topics, normalized by the maximum difference in probability of any word between the two topics.

plot.STM(topics7, type = "perspectives", topics = c(5,7))

Wordclouds for topics

We can also learn more about each topic with wordclouds. The first plot shows marginal probability of words in the corpus. We are plotting top 100 words.

cloud(topics7, topic = NULL, scale = c(3, .25), max.words = 100)

Wordcloud for Topic 1:

cloud(topics7, topic = 1, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 2:

cloud(topics7, topic = 2, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 3:

cloud(topics7, topic = 3, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 4:

cloud(topics7, topic = 4, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 5:

cloud(topics7, topic = 5, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 6:

cloud(topics7, topic = 6, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 7:

cloud(topics7, topic = 7, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Estimating relationship between metadata (conditionality) and topic prevalence

We look at the relationship between topic proportions and conditionality factor. Confidence intervals produced by the method of composition in STM allow us to pick up statistical uncertainty in the linear regression model.

con.eff <- estimateEffect( ~ factor(condition), 
                          topics7, meta = stm.dfm$meta, 
                          uncertainty = "Global")

We now plot the results of the analysis as the difference in topic proportions for two different values of conditionality (before and after the introduction of the policy). Point estimates and 95% confidence intervals plotted.

plot(con.eff, covariate = "condition",  
     model = topics7, method = "difference", 
     cov.value1 = 1, cov.value2 = 0, verbose.labels = FALSE, xlim = c(-.5, .7),
     main = "Effect of Conditionality")

Figure shows a treatment effect of conditionality introduction in all seven topics, comparing programs before and after introduction of conditionality.

We observe that conditionality introduction had an effect only on Topic 2, while for the remaining topics the effect of conditionality is not distinguishable from zero.

On average, the difference between the proportion of regional innovation programs that discuss Topic 2 after introduction of conditionality requirement and the proportion of programs that discuss Topic 2 before conditionality introduction is .38 (.16, .6).

Correlation between topics

We can also assess the relationship between topics in the STM framework that allows correlations between topics. Positive correlations between topics suggest that both topics are likely to be covered within an innovation program.

topic.cor <- topicCorr(topics7)
plot.topicCorr(topic.cor)

It appears that only Topics 1 and 5 are linked at the default 0.01 correlation cutoff.

Poland

Tokenizing documents.

#tokenizing
tok <- tokens(pl_corpus, what = "word",
              removePunct = TRUE,
              removeSymbols = TRUE,
              removeNumbers = TRUE,
              removeTwitter = TRUE,
              removeURL = TRUE,
              removeHyphens = TRUE,
              verbose = TRUE)
Starting tokenization...
...tokenizing 1 of 1 blocks...
, removing URLs...hashing tokens
...total elapsed:  0.657000000000153 seconds.
Finished tokenizing and cleaning 28 texts.

Creating document feature matrix.

dfm <- dfm(tok, 
           tolower = TRUE,
           remove= c(stopwords("SMART"), "melt", "hessen", "hamburg", "schleswig", "holstein",
                     "bavaria", "bavarian", "berlin", "bremen", "saxoni", "northrhine", "westphalia",
                     "rhineland", "saarland", "mecklenburg", "wÿrttemberg", "baden", "anhalt",
                     "chsischen", "chsisch", "pomorski", "zachodniopomorski", "kujawsko", "łódź",
                     "podkarpacki", "mazovia", "mazowiecki", "pomerania", "świętokrzyski",
                     "podlaski",
                     "warmia", "lubuski", "malopolska", "małopolsk", "wielkopolska", "sląskie",
                     "działao", "mazuri", "olsztyn", "łódzkie", "mazurskiego", "góra", "silesian",
                     "warsaw", "rzeszów", "mazowsz", "mazowieckich", "małopolska", "małopolski",
                     "śląskie", "kraków", "alentejo", "tejo", "lisboa", "azor", "algarv", "czech",
                     "republ", "tejo", "sociedad", "madeira", "lisbon", "saxoni", "bavaria",
                     "sachsen"),
           stem=TRUE, 
           verbose = TRUE)
Creating a dfm from a tokens object ...
   ... lowercasing
   ... found 28 documents, 22,192 features
   ... removed 494 features, from 632 supplied (glob) feature types
   ... stemming features (English), trimmed 4761 feature variants
   ... created a 28 x 16,937 sparse dfm
   ... complete. 
Elapsed time: 0.407 seconds.
#Removing any digits. `dfm` picks up any separated digits, not digits that are part of tokens.
dfm.m <- dfm_select(dfm, '[\\d-]',  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 400 features, from 1 supplied (regex) feature types
#Removing any punctuation. `dfm` picks up any punctuation unless it's part of a token.
dfm.m <- dfm_select(dfm.m, "[[:punct:]]",  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 301 features, from 1 supplied (regex) feature types
#Removing any tokens less than four characters.
dfm.m <- dfm_select(dfm.m, '^.{1,3}$',  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 1,358 features, from 1 supplied (regex) feature types
#Dropping words that appear less than 5 times and in less than 3 documents.
dfm.trim <- dfm_trim(dfm.m, min_count = 5, min_docfreq = 3)
Removing features occurring: 
  - fewer than 5 times: 11,008
  - in fewer than 3 documents: 10,856
  Total features removed: 11,555 (77.7%).
topfeatures(dfm.trim, n = 50)
   region     innov   develop technolog   support  strategi      busi  research implement 
    15807     14102     10662      4813      4492      4306      4173      3940      3761 
    activ   project      area   product  institut  industri    econom specialis    servic 
     3752      3526      3481      3423      3237      2934      2899      2888      2868 
  compani    number    cooper    sector      oper    system      fund   process    object 
     2825      2768      2766      2759      2705      2683      2682      2558      2548 
 european   increas   economi      educ    includ  programm     level    poland     centr 
     2548      2378      2309      2249      2247      2156      2141      2089      2080 
enterpris    inform    market   potenti    public    action    invest      year     smart 
     2049      2011      1981      1974      1951      1937      1880      1823      1816 
   promot      high    nation      base  competit 
     1814      1812      1795      1747      1743 
sparsity(dfm.trim)
[1] 0.5407119
nfeature(dfm.trim)
[1] 3323

Converting DFM into format for STM package

stm.dfm <- convert(dfm.trim, to = "stm",  docvars = docvars(pl_corpus))

Analysis

In the analysis we consider the effect of introducing conditionality on the content of innovation programs. In order to achieve that we implement a structural topic model (Roberts et al., 2015). We model topic prevalence in the context of the conditionality condition marking programs before and after 2013. In addition, we control for region fixed effects. The aim is to allow the observed metadata to affect the frequency with which a topic is discussed in innovation programs. This allows us to test the degree of association between conditionality (and region effects) and the average proportion of a document discussing a topic.

Searching for optimal number of topics

We assess the optimal number of topics that need to specified for the STM analysis. We follow original STM paper and focus on exclusivity and semantic coherence measures. Mimno et al. (2011) propose semantic coherence measure, closely related to point-wise mutual information measure proposed by Newman et al. (2010) to evaluate topic quality. Mimno et al. (2011) show that semantic coherence corresponds to expert judgments and more general human judgments in Amazon’s Mechanical Turk experiments.

Exclusivity score for each topic follows Bischof and Airoldi (2012). Highly frequent words in a given topic that don’t appear too often in other topics are said to make that topic exclusive. Cohesive and exclusive topics are more semantically useful. Following Roberts et al. (2015) we generate a set of candidate models ranging between 3 and 50 topics.

We then plot the exclusivity and semantic coherence (numbers closer to zero indicate higher coherence), and select a model on the semantic coherence-exclusivity “frontier”, that is, where no model strictly dominates another in terms of semantic coherence and exclusivity.

#pdf("search.pdf")
par(mar=c(5,4,4,5)+.1)
plot(search$results$K,search$results$exclus,type="l",col="red", 
     xlab="Number of topics", ylab="Exclusivity")
axis(side=1,at=seq(0,50,5))
#abline(v=c(5,10), col="green")
par(new=TRUE)
plot(search$results$K, search$results$semcoh,
     type="l",col="blue",xaxt="n",yaxt="n",xlab="",ylab="")
axis(4)
mtext("Semantic Coherence",side=4,line=3)
legend("right",col=c("red","blue"),lty=1,legend=c("excl","sem coh"))

#dev.off()

We select the model with 6 topics for our analysis – there’s a drop in semantic coherence after \(k=6\). We estimate the model with conditionality and region covariates.

Exploring words associated with each topic.

One way to summarize topics is to combine term frequency and exclusivity to that topic into a univariate summary statistic. In STM package this is implemented as FREX following Bischof and Airoldi (2012) and Airoldi and Bischof (2016). The logic behind this measure is that both frequency and exclusivity are important factors in determining semantic content of a word and form a two dimensional summary of topical content. FREX is the geometric average of frequency and exclusivity and can be viewed as a univariate measure of topical importance. STM authors suggest that nonexclusive words are less likely to carry topic-specific content, while infrequent words occur too rarely to form the semantic core of a topic. FREX is therefore combining information from the most frequent words in the corpus that are also likely to have been generated from the topic of interest to summarize its content.

labelTopics(topics6)
Topic 1 Top Words:
     Highest Prob: innov, region, develop, strategi, technolog, support, implement 
     FREX: pomorski, firm, januari, smes, action, zachodniopomorski, version 
     Lift: instig, urgenc, kreatorem, exempt, boast, branżowo, consent 
     Score: urgenc, pomorski, innov, bydgoszcz, irop, region, irdop 
Topic 2 Top Words:
     Highest Prob: region, develop, specialis, innov, smart, strategi, manufactur 
     FREX: świętokrzyski, prospect, podlaski, updat, manufactur, drawn, cent 
     Lift: shore, metalowo, venu, error, mail, percent, super 
     Score: shore, pomorski, smart, świętokrzyski, kielc, podlaski, specialis 
Topic 3 Top Words:
     Highest Prob: region, develop, area, social, econom, support, increas 
     FREX: mazuri, urban, municip, citi, mazowsz, rural, central 
     Lift: bozena, bzura, habitat, lagoon, pilica, rozwiązao, łódz 
     Score: rozwiązao, mazuri, bovin, jakośd, dostępnośd, społeczeostwo, wartośd 
Topic 4 Top Words:
     Highest Prob: innov, region, develop, technolog, busi, research, support 
     FREX: lubuski, lubelski, quantiti, egionalna, lublin, smes, scheme 
     Lift: bytom, cowników, darczej, doradczej, finansowa, gionalnego, gliwic 
     Score: gliwic, lubuski, egionalna, kielc, przedsiębior, świętokrzyski, irop 
Topic 5 Top Words:
     Highest Prob: innov, region, develop, specialis, area, smart, technolog 
     FREX: podkarpacki, wielkopolski, chain, discoveri, food, specialis, smart 
     Lift: aerospac, counteract, cosm, bioeconomi, reproduc, furnish, specjalizacji 
     Score: aerospac, smart, bioeconomi, podkarpacki, specialis, ibid, foray 
Topic 6 Top Words:
     Highest Prob: region, innov, develop, project, technolog, research, busi 
     FREX: małopolski, west, realis, pomeranian, compet, financ, project 
     Lift: meta, inextric, prosum, westpomeranian, małopolski, jagiellonian, dispers 
     Score: meta, pomeranian, małopolski, prosum, realis, smart, ecosystem 

Plotting the same:

plot(topics6,type="labels", n = 10, text.cex = .5)

Graphical display of estimated topic proportions

Here we have expected proportions of the corpus that belongs to each topic.

plot(topics6,type="summary", xlim = c(0, 1), n = 10, text.cex = .5)

Topical perspectives

Topics 4 and 1 appear to have very similar top words. We can plot the contrast in words across these two topics. This plot calculates the difference in probability of a word for the two topics, normalized by the maximum difference in probability of any word between the two topics.

plot.STM(topics6, type = "perspectives", topics = c(4,1))

Wordclouds for topics

We can also learn more about each topic with wordclouds. The first plot shows marginal probability of words in the corpus. We are plotting top 100 words.

cloud(topics6, topic = NULL, scale = c(2, .25), max.words = 100)

Wordcloud for Topic 1:

cloud(topics6, topic = 1, scale = c(4, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 2:

cloud(topics6, topic = 2, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 3:

cloud(topics6, topic = 3, scale = c(4, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 4:

cloud(topics6, topic = 4, scale = c(4, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 5:

cloud(topics6, topic = 5, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 6:

cloud(topics6, topic = 6, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Estimating relationship between metadata (conditionality) and topic prevalence

We look at the relationship between topic proportions and conditionality factor. Confidence intervals produced by the method of composition in STM allow us to pick up statistical uncertainty in the linear regression model.

con.eff <- estimateEffect( ~ factor(condition), 
                          topics6, meta = stm.dfm$meta, 
                          uncertainty = "Global")

We now plot the results of the analysis as the difference in topic proportions for two different values of conditionality (before and after the introduction of the policy). Point estimates and 95% confidence intervals plotted.

plot(con.eff, covariate = "condition",  
     model = topics6, method = "difference", 
     cov.value1 = 1, cov.value2 = 0, verbose.labels = FALSE, xlim = c(-1, 1),
     main = "Effect of Conditionality")

Figure shows a treatment effect of conditionality introduction in all six topics, comparing programs before and after introduction of conditionality.

We observe that conditionality introduction had an effect on Topics 2, 4, and 5, while for the remaining topics the effect of conditionality is not distinguishable from zero. While conditionality increased the use of Topics 2 and 5, it decreased the use of Topic 4.

On average, the difference between the proportion of regional innovation programs that discuss Topic 2 and Topic 5 after introduction of conditionality requirement and the proportion of programs that discuss Topics 2 and 5 before conditionality introduction is 0.4. At the same time there’s a similar scale degrease in the discussion of Topic 4.

Correlation between topics

We can also assess the relationship between topics in the STM framework that allows correlations between topics. Positive correlations between topics suggest that both topics are likely to be covered within an innovation program.

topic.cor <- topicCorr(topics6)
plot.topicCorr(topic.cor)

It appears that none of the topics are linked at the default 0.01 correlation cutoff.

Portugal

Tokenizing documents.

#tokenizing
tok <- tokens(pt_corpus, what = "word",
              removePunct = TRUE,
              removeSymbols = TRUE,
              removeNumbers = TRUE,
              removeTwitter = TRUE,
              removeURL = TRUE,
              removeHyphens = TRUE,
              verbose = TRUE)
Starting tokenization...
...tokenizing 1 of 1 blocks...
, removing URLs...hashing tokens
...total elapsed:  0.513999999999996 seconds.
Finished tokenizing and cleaning 16 texts.

Creating document feature matrix.

dfm <- dfm(tok, 
           tolower = TRUE,
           remove= c(stopwords("SMART"), "melt", "hessen", "hamburg", "schleswig", "holstein",
                     "bavaria", "bavarian", "berlin", "bremen", "saxoni", "northrhine", "westphalia",
                     "rhineland", "saarland", "mecklenburg", "wÿrttemberg", "baden", "anhalt",
                     "chsischen", "chsisch", "pomorski", "zachodniopomorski", "kujawsko", "łódź",
                     "podkarpacki", "mazovia", "mazowiecki", "pomerania", "świętokrzyski",
                     "podlaski",
                     "warmia", "lubuski", "malopolska", "małopolsk", "wielkopolska", "sląskie",
                     "działao", "mazuri", "olsztyn", "łódzkie", "mazurskiego", "góra", "silesian",
                     "warsaw", "rzeszów", "mazowsz", "mazowieckich", "małopolska", "małopolski",
                     "śląskie", "kraków", "alentejo", "tejo", "lisboa", "azor", "algarv", "czech",
                     "republ", "tejo", "sociedad", "madeira", "lisbon", "saxoni", "bavaria",
                     "sachsen"),
           stem=TRUE, 
           verbose = TRUE)
Creating a dfm from a tokens object ...
   ... lowercasing
   ... found 16 documents, 17,383 features
   ... removed 456 features, from 632 supplied (glob) feature types
   ... stemming features (English), trimmed 4908 feature variants
   ... created a 16 x 12,019 sparse dfm
   ... complete. 
Elapsed time: 0.374 seconds.
#Removing any digits. `dfm` picks up any separated digits, not digits that are part of tokens.
dfm.m <- dfm_select(dfm, '[\\d-]',  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 317 features, from 1 supplied (regex) feature types
#Removing any punctuation. `dfm` picks up any punctuation unless it's part of a token.
dfm.m <- dfm_select(dfm.m, "[[:punct:]]",  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 233 features, from 1 supplied (regex) feature types
#Removing any tokens less than four characters.
dfm.m <- dfm_select(dfm.m, '^.{1,3}$',  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 1,139 features, from 1 supplied (regex) feature types
#Dropping words that appear less than 5 times and in less than 3 documents.
dfm.trim <- dfm_trim(dfm.m, min_count = 5, min_docfreq = 3)
Removing features occurring: 
  - fewer than 5 times: 6,827
  - in fewer than 3 documents: 6,915
  Total features removed: 7,307 (70.7%).
topfeatures(dfm.trim, n = 50)
   region   develop      area     innov   product technolog     activ    sector    promot 
     9811      4327      3789      3494      3056      3044      2691      2387      2224 
 strategi    system   support    nation   project     level   resourc      busi  research 
     2176      2038      1981      1967      1814      1808      1783      1762      1697 
  tourism    polici    econom specialis    public    servic  programm  industri     centr 
     1678      1657      1654      1642      1628      1527      1480      1430      1414 
 competit      plan    market     manag  structur     smart territori  prioriti    action 
     1365      1363      1332      1320      1318      1316      1313      1238      1216 
  strateg  knowledg     figur implement    intern   increas   potenti    portug   network 
     1208      1170      1166      1160      1159      1147      1140      1125      1112 
  process  european    invest      oper     relat 
     1109      1095      1084      1080      1070 
sparsity(dfm.trim)
[1] 0.4473412
nfeature(dfm.trim)
[1] 3023

Converting DFM into format for STM package

stm.dfm <- convert(dfm.trim, to = "stm",  docvars = docvars(pt_corpus))

Analysis

In the analysis we consider the effect of introducing conditionality on the content of innovation programs. In order to achieve that we implement a structural topic model (Roberts et al., 2015). We model topic prevalence in the context of the conditionality condition marking programs before and after 2013. In addition, we control for region fixed effects. The aim is to allow the observed metadata to affect the frequency with which a topic is discussed in innovation programs. This allows us to test the degree of association between conditionality (and region effects) and the average proportion of a document discussing a topic.

Searching for optimal number of topics

We assess the optimal number of topics that need to specified for the STM analysis. We follow original STM paper and focus on exclusivity and semantic coherence measures. Mimno et al. (2011) propose semantic coherence measure, closely related to point-wise mutual information measure proposed by Newman et al. (2010) to evaluate topic quality. Mimno et al. (2011) show that semantic coherence corresponds to expert judgments and more general human judgments in Amazon’s Mechanical Turk experiments.

Exclusivity score for each topic follows Bischof and Airoldi (2012). Highly frequent words in a given topic that don’t appear too often in other topics are said to make that topic exclusive. Cohesive and exclusive topics are more semantically useful. Following Roberts et al. (2015) we generate a set of candidate models ranging between 3 and 50 topics.

We then plot the exclusivity and semantic coherence (numbers closer to zero indicate higher coherence), and select a model on the semantic coherence-exclusivity “frontier”, that is, where no model strictly dominates another in terms of semantic coherence and exclusivity.

par(mar=c(5,4,4,5)+.1)
plot(search$results$K,search$results$exclus,type="l",col="red", 
     xlab="Number of topics", ylab="Exclusivity")
axis(side=1,at=seq(0,50,5))
#abline(v=c(5,10), col="green")
par(new=TRUE)
plot(search$results$K, search$results$semcoh,
     type="l",col="blue",xaxt="n",yaxt="n",xlab="",ylab="")
axis(4)
mtext("Semantic Coherence",side=4,line=3)
legend("right",col=c("red","blue"),lty=1,legend=c("excl","sem coh"))

We select the model with 10 topics for our analysis – there’s no improvement in semantic coherence after \(k=10\). We estimate the model with conditionality and region covariates.

Exploring words associated with each topic.

One way to summarize topics is to combine term frequency and exclusivity to that topic into a univariate summary statistic. In STM package this is implemented as FREX following Bischof and Airoldi (2012) and Airoldi and Bischof (2016). The logic behind this measure is that both frequency and exclusivity are important factors in determining semantic content of a word and form a two dimensional summary of topical content. FREX is the geometric average of frequency and exclusivity and can be viewed as a univariate measure of topical importance. STM authors suggest that nonexclusive words are less likely to carry topic-specific content, while infrequent words occur too rarely to form the semantic core of a topic. FREX is therefore combining information from the most frequent words in the corpus that are also likely to have been generated from the topic of interest to summarize its content.

labelTopics(topics10)
Topic 1 Top Words:
     Highest Prob: region, project, programm, technolog, action, support, innov 
     FREX: vale, approv, report, final, submit, project, steer 
     Lift: ritt, prai, tagusvalley, ourém, oest, reprogram, iasp 
     Score: ritt, tagusvalley, project, vale, prai, programm, reprogram 
Topic 2 Top Words:
     Highest Prob: region, develop, specialis, smart, product, activ, technolog 
     FREX: northern, ration, smart, specialis, comput, asset, textil 
     Lift: coat, tractor, symbol, valor, cumul, grade, spice 
     Score: coat, smart, specialis, northern, manufactur, cloth, textil 
Topic 3 Top Words:
     Highest Prob: programm, innov, fund, project, region, oper, financi 
     FREX: regul, erdf, articl, elig, expenditur, member, financi 
     Lift: merg, debt, hear, statutori, oblig, projecto, multiannu 
     Score: merg, projecto, erdf, gender, debt, hear, articl 
Topic 4 Top Words:
     Highest Prob: area, region, urban, territori, develop, system, promot 
     FREX: prot, urban, beira, serra, mondego, road, corridor 
     Lift: serra, prohibit, prot, mondego, alta, corridor, pinhal 
     Score: serra, mondego, inst, beira, leiria, pinhal, viseu 
Topic 5 Top Words:
     Highest Prob: region, centr, innov, central, portug, product, area 
     FREX: central, portug, centr, materi, tice, manufactur, forest 
     Lift: pulp, quotient, politécnico, biocant, fraqueza, ppas, toxicolog 
     Score: pulp, tice, smart, central, centr, quotient, biocant 
Topic 6 Top Words:
     Highest Prob: region, azor, develop, tourism, area, activ, innov 
     FREX: azor, autonom, island, livestock, fisheri, govern, fish 
     Lift: azor, island, archipelago, campus, galician, dive, canari 
     Score: azor, smart, island, autonom, tourism, campus, outermost 
Topic 7 Top Words:
     Highest Prob: region, innov, area, develop, technolog, strategi, promot 
     FREX: version, decemb, polici, smart, climat, internationalis, align 
     Lift: listen, repositori, postgradu, subsoil, ipctn, esif, dgeec 
     Score: listen, smart, specialis, version, decemb, esif, satellit 
Topic 8 Top Words:
     Highest Prob: region, sector, product, innov, technolog, project, level 
     FREX: augusto, mateus, advis, sociedad, drawn, team, graph 
     Lift: augusto, mateus, sociedad, decor, graph, advis, mediat 
     Score: augusto, mateus, advis, sociedad, graph, cork, aeronaut 
Topic 9 Top Words:
     Highest Prob: region, algarv, activ, sector, innov, product, develop 
     FREX: algarv, faro, ccdr, season, unemploy, aquacultur, accommod 
     Lift: motorcycl, olhão, tavira, algarv, footnot, faro, iefp 
     Score: motorcycl, algarv, faro, smart, tourism, aquacultur, albufeira 
Topic 10 Top Words:
     Highest Prob: region, develop, nation, public, territori, oper, polici 
     FREX: nsrf, north, converg, cohes, portugues, page, scenario 
     Lift: tecno, braga, offset, infor, page, gothenburg, manoeuvr 
     Score: tecno, nsrf, north, page, territori, douro, gender 

Plotting the same:

plot(topics10,type="labels", n = 10, text.cex = .5)

Graphical display of estimated topic proportions

Here we have expected proportions of the corpus that belongs to each topic.

plot(topics10,type="summary", xlim = c(0, 1), n = 10, text.cex = .5)

Topical perspectives

Topics 7 and 1 appear to have very similar top words. We can plot the contrast in words across these two topics. This plot calculates the difference in probability of a word for the two topics, normalized by the maximum difference in probability of any word between the two topics.

plot.STM(topics10, type = "perspectives", topics = c(7,1))

Wordclouds for topics

We can also learn more about each topic with wordclouds. The first plot shows marginal probability of words in the corpus. We are plotting top 100 words.

cloud(topics10, topic = NULL, scale = c(2, .25), max.words = 100)

Wordcloud for Topic 1:

cloud(topics10, topic = 1, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 2:

cloud(topics10, topic = 2, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 3:

cloud(topics10, topic = 3, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 4:

cloud(topics10, topic = 4, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 5:

cloud(topics10, topic = 5, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 6:

cloud(topics10, topic = 6, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 7:

cloud(topics10, topic = 7, scale = c(3, .1), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 8:

cloud(topics10, topic = 8, scale = c(3, .3), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 9:

cloud(topics10, topic = 9, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 10:

cloud(topics10, topic = 10, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Estimating relationship between metadata (conditionality) and topic prevalence

We look at the relationship between topic proportions and conditionality factor. Confidence intervals produced by the method of composition in STM allow us to pick up statistical uncertainty in the linear regression model.

con.eff <- estimateEffect( ~ factor(condition), 
                          topics10, meta = stm.dfm$meta, 
                          uncertainty = "Global")

We now plot the results of the analysis as the difference in topic proportions for two different values of conditionality (before and after the introduction of the policy). Point estimates and 95% confidence intervals plotted.

plot(con.eff, covariate = "condition",  
     model = topics10, method = "difference", 
     cov.value1 = 1, cov.value2 = 0, verbose.labels = FALSE, xlim = c(-1, 1),
     ci.level=.95,
     main = "Effect of Conditionality")

Figure shows a treatment effect of conditionality introduction in all ten topics, comparing programs before and after introduction of conditionality.

We observe that conditionality introduction had an effect on Topic 7, while for the remaining topics the effect of conditionality is not distinguishable from zero.

On average, the difference between the proportion of regional innovation programs that discuss Topic 7 after introduction of conditionality requirement and the proportion of programs that discuss Topic 7 before conditionality introduction is 0.4.

Correlation between topics

We can also assess the relationship between topics in the STM framework that allows correlations between topics. Positive correlations between topics suggest that both topics are likely to be covered within an innovation program.

topic.cor <- topicCorr(topics10)
plot.topicCorr(topic.cor)

It appears that Topics 3 and 10 are linked at the default 0.01 correlation cutoff.

Czech Republic

Tokenizing documents.

#tokenizing
tok <- tokens(cz_corpus, what = "word",
              removePunct = TRUE,
              removeSymbols = TRUE,
              removeNumbers = TRUE,
              removeTwitter = TRUE,
              removeURL = TRUE,
              removeHyphens = TRUE,
              verbose = TRUE)
Starting tokenization...
...tokenizing 1 of 1 blocks...
, removing URLs...hashing tokens
...total elapsed:  0.15300000000002 seconds.
Finished tokenizing and cleaning 3 texts.

Creating document feature matrix.

dfm <- dfm(tok, 
           tolower = TRUE,
           remove= c(stopwords("SMART"), "melt", "hessen", "hamburg", "schleswig", "holstein",
                     "bavaria", "bavarian", "berlin", "bremen", "saxoni", "northrhine", "westphalia",
                     "rhineland", "saarland", "mecklenburg", "wÿrttemberg", "baden", "anhalt",
                     "chsischen", "chsisch", "pomorski", "zachodniopomorski", "kujawsko", "łódź",
                     "podkarpacki", "mazovia", "mazowiecki", "pomerania", "świętokrzyski",
                     "podlaski", "warmia", "lubuski", "malopolska", "małopolsk", "wielkopolska",
                     "sląskie", " republ", 
                     "działao", "mazuri", "olsztyn", "łódzkie", "mazurskiego", "góra", "silesian",
                     "warsaw", "rzeszów", "mazowsz", "mazowieckich", "małopolska", "małopolski",
                     "śląskie", "kraków", "alentejo", "tejo", "lisboa", "azor", "algarv", "czech",
                     "republ", "tejo", "sociedad", "madeira", "lisbon", "saxoni", "bavaria",
                     "sachsen"),
           stem=TRUE, 
           verbose = TRUE)
Creating a dfm from a tokens object ...
   ... lowercasing
   ... found 3 documents, 7,068 features
   ... removed 401 features, from 633 supplied (glob) feature types
   ... stemming features (English), trimmed 2318 feature variants
   ... created a 3 x 4,349 sparse dfm
   ... complete. 
Elapsed time: 0.264 seconds.
#Removing any digits. `dfm` picks up any separated digits, not digits that are part of tokens.
dfm.m <- dfm_select(dfm, '[\\d-]',  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 103 features, from 1 supplied (regex) feature types
#Removing any punctuation. `dfm` picks up any punctuation unless it's part of a token.
dfm.m <- dfm_select(dfm.m, "[[:punct:]]",  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 35 features, from 1 supplied (regex) feature types
#Removing any tokens less than four characters.
dfm.m <- dfm_select(dfm.m, '^.{1,3}$',  selection = "remove", 
                    valuetype="regex", verbose = TRUE)
removed 364 features, from 1 supplied (regex) feature types
#Dropping words that appear less than 2 times and in less than 2 documents.
dfm.trim <- dfm_trim(dfm.m, min_count = 2, min_docfreq = 2)
Removing features occurring: 
  - fewer than 2 times: 1,449
  - in fewer than 2 documents: 2,138
  Total features removed: 2,138 (55.6%).
topfeatures(dfm.trim, n = 50)
     research        republ       develop         innov        public        nation       support 
         1441          1066          1053           928           613           544           520 
       econom       increas         level         activ        system          busi      strategi 
          488           459           459           452           451           435           431 
       region      programm        growth        sector          area     implement      knowledg 
          422           418           411           403           393           370           363 
     competit          firm        result          fund       qualiti        servic        intern 
          351           338           334           330           329           327           323 
    technolog       countri          educ         manag        market       resourc         state 
          321           317           316           313           303           296           285 
      product        polici        number       organis       economi      industri          term 
          285           281           276           273           271           265           261 
       object     specialis       foreign       project        invest          high      european 
          257           256           254           253           252           251           236 
infrastructur 
          231 
sparsity(dfm.trim)
[1] 0.1677394
nfeature(dfm.trim)
[1] 1709

Converting DFM into format for STM package

stm.dfm <- convert(dfm.trim, to = "stm",  docvars = docvars(cz_corpus))

Analysis

In the analysis we consider the effect of introducing conditionality on the content of innovation programs. In order to achieve that we implement a structural topic model (Roberts et al., 2015). We model topic prevalence in the context of the conditionality condition marking programs before and after 2013. In contrast to the above analysis, we do not control for region fixed effects as we have only Czech national documents. The aim is to allow the observed metadata to affect the frequency with which a topic is discussed in innovation programs. This allows us to test the degree of association between conditionality (and region effects) and the average proportion of a document discussing a topic.

Given that we have only three documents for CZ, we cannot perform the topic search procedures we implemented above. To keep it in context we settle for the number of topics similar to previous analyses (six topics).

Exploring words associated with each topic.

One way to summarize topics is to combine term frequency and exclusivity to that topic into a univariate summary statistic. In STM package this is implemented as FREX following Bischof and Airoldi (2012) and Airoldi and Bischof (2016). The logic behind this measure is that both frequency and exclusivity are important factors in determining semantic content of a word and form a two dimensional summary of topical content. FREX is the geometric average of frequency and exclusivity and can be viewed as a univariate measure of topical importance. STM authors suggest that nonexclusive words are less likely to carry topic-specific content, while infrequent words occur too rarely to form the semantic core of a topic. FREX is therefore combining information from the most frequent words in the corpus that are also likely to have been generated from the topic of interest to summarize its content.

labelTopics(topics6)
Topic 1 Top Words:
     Highest Prob: research, develop, innov, support, republ, activ, public 
     FREX: earmark, support, prioriti, research, evalu, societi, activ 
     Lift: earmark, foresight, compos, under, opei, specialist, onward 
     Score: earmark, vavpl, research, commercialis, aspect, excel, opei 
Topic 2 Top Words:
     Highest Prob: econom, public, growth, strategi, develop, legisl, republ 
     FREX: pass, languag, final, output, insur, land, transport 
     Lift: unemploy, pass, taxat, land, court, privatis, fiscal 
     Score: unemploy, languag, pass, insur, case, privatis, final 
Topic 3 Top Words:
     Highest Prob: research, republ, innov, develop, nation, firm, region 
     FREX: intervent, specialis, domain, digit, manufactur, firm, talent 
     Lift: domain, vertic, intervent, specialis, experiment, talent, evid 
     Score: domain, intervent, case, manufactur, digit, tabl, specialis 
Topic 4 Top Words:
     Highest Prob: research, develop, innov, republ, support, activ, public 
     FREX: research, innov, develop, activ, knowledg, object, organis 
     Lift: defenc, vavpl, pursuit, mediatis, nerv, news, panel 
     Score: defenc, research, innov, develop, vavpl, excel, commercialis 
Topic 5 Top Words:
     Highest Prob: research, develop, innov, support, liabil, republ, public 
     FREX: liabil, support, prioriti, evalu, polici, develop, activ 
     Lift: liabil, scarc, abovement, voucher, ecop, announc, white 
     Score: liabil, research, support, develop, innov, prioriti, activ 
Topic 6 Top Words:
     Highest Prob: research, develop, innov, support, republ, deadlin, public 
     FREX: deadlin, support, prioriti, polici, evalu, develop, establish 
     Lift: deadlin, scarc, abovement, voucher, announc, august, buoyant 
     Score: deadlin, research, support, develop, innov, prioriti, activ 

Plotting the same:

plot(topics6,type="labels", n = 10, text.cex = .5)

Graphical display of estimated topic proportions

Here we have expected proportions of the corpus that belongs to each topic.

plot(topics6,type="summary", xlim = c(0, 1), n = 10, text.cex = .5)

Topical perspectives

Topics 8 and 1 appear to have very similar top words. We can plot the contrast in words across these two topics. This plot calculates the difference in probability of a word for the two topics, normalized by the maximum difference in probability of any word between the two topics.

plot.STM(topics6, type = "perspectives", topics = c(2,3))

Wordclouds for topics

We can also learn more about each topic with wordclouds. The first plot shows marginal probability of words in the corpus. We are plotting top 100 words.

cloud(topics6, topic = NULL, scale = c(2, .25), max.words = 100)

Wordcloud for Topic 1:

cloud(topics6, topic = 1, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 2:

cloud(topics6, topic = 2, scale = c(3, .3), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 3:

cloud(topics6, topic = 3, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 4:

cloud(topics6, topic = 4, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 5:

cloud(topics6, topic = 5, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Wordcloud for Topic 6:

cloud(topics6, topic = 6, scale = c(3, .5), random.order = FALSE,rot.per = .3, max.words = 100)

Estimating relationship between metadata (conditionality) and topic prevalence

We look at the relationship between topic proportions and conditionality factor. Confidence intervals produced by the method of composition in STM allow us to pick up statistical uncertainty in the linear regression model.

con.eff <- estimateEffect( ~ factor(condition), 
                          topics6, meta = stm.dfm$meta, 
                          uncertainty = "Global")

We now plot the results of the analysis as the difference in topic proportions for two different values of conditionality (before and after the introduction of the policy). Point estimates and 95% confidence intervals plotted.

plot(con.eff, covariate = "condition",  
     model = topics6, method = "difference", 
     cov.value1 = 1, cov.value2 = 0, verbose.labels = FALSE, xlim = c(-1, 1),
     ci.level=.95,
     main = "Effect of Conditionality")

Figure shows a treatment effect of conditionality introduction in all six topics, comparing programs before and after introduction of conditionality.

We observe that conditionality introduction had an effect on Topic 3, while for the remaining topics the effect of conditionality is not distinguishable from zero.

On average, the difference between the proportion of regional innovation programs that discuss Topic 3 after introduction of conditionality requirement and the proportion of programs that discuss Topic 3 before conditionality introduction is 0.8.

Correlation between topics

We can also assess the relationship between topics in the STM framework that allows correlations between topics. Positive correlations between topics suggest that both topics are likely to be covered within an innovation program.

topic.cor <- topicCorr(topics6)
plot.topicCorr(topic.cor)

It appears that all topics apart from Topic 2 are linked at the default 0.01 correlation cutoff.

LS0tCnRpdGxlOiAiVW5kZXJzdGFuZGluZyBUaGUgRWZmZWN0IG9mIENvbmRpdGlvbmFsaXR5IG9uIFJlZ2lvbmFsIElubm92YXRpb24gUHJvZ3JhbXMiCmF1dGhvcjoKLSBhZmZpbGlhdGlvbjogRUMgSlJDCiAgZW1haWw6IEFsZXhhbmRlci5LTEVJQlJJTktAZWMuZXVyb3BhLmV1CiAgbmFtZTogQWxleGFuZGVyIEtsZWlicmluawotIGFmZmlsaWF0aW9uOiBVbml2ZXJzaXR5IG9mIEVzc2V4CiAgZW1haWw6IHMubWlraGF5bG92QGVzc2V4LmFjLnVrCiAgbmFtZTogU2xhdmEgTWlraGF5bG92CmRhdGU6ICIxNCBGZWJydWFyeSAyMDE3IgpvdXRwdXQ6CiAgd29yZF9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIHRvYzogeWVzCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAp0aGFua3M6IEF1dGhvcnMnIG5hbWVzIGFyZSBsaXN0ZWQgaW4gYWxwaGFiZXRpY2FsIG9yZGVyLiBBdXRob3JzIGhhdmUgY29udHJpYnV0ZWQKICBlcXVhbGx5IHRvIGFsbCB3b3JrLgotLS0KCgoKCgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KI0xvYWRpbmcgcGFja2FnZXMgYW5kIGRhdGEKbGlicmFyeShyZWFkdGV4dCkKbGlicmFyeShxdWFudGVkYSkKbGlicmFyeShzdG0pCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShnZ3Bsb3QyKQpgYGAKCldlIGNvbGxlY3RlZCBkYXRhIG9uIHJlZ2lvbmFsIGlubm92YXRpb24gcHJvZ3JhbXMgZm9yIHRoZSBmb2xsb3dpbmcgRVUgbWVtYmVyIHN0YXRlcyAoQ3plY2ggUmVwdWJsaWMsIEdlcm1hbnksIFBvbGFuZCwgUG9ydHVnYWwsIGFuZCBVSykuIFJlZ2lvbmFsIHByb2dyYW1zIGFyZSBhdmFpbGFibGUgZm9yIHR3byB0aW1lIHBlcmlvZHM6IGJlZm9yZSBhbmQgYWZ0ZXIgaW50cm9kdWN0aW9uIG9mIGNvbmRpdGlvbmFsaXR5IGluIDIwMTMuIAoKSGVyZSB3ZSBsb29rIGF0IHJlZ2lvbmFsIHByb2dyYW1zLCB1c3VhbGx5IGRyYWZ0ZWQgYnkgTlVUUzIgbGV2ZWwgYXV0aG9yaXRpZXMsIGFuZCBub3QgbW9yZSBnZW5lcmFsIHN0YXRlIHByb2dyYW1zLiBUaGUgZXhjZXB0aW9uIGlzIEN6ZWNoIFJlcHVibGljIHRoYXQgY29uc2lzdHMgb2YgTlVUUzEgcmVnaW9ucyBvbmx5LiAKCldlIHBlcmZvcm0gYW5hbHlzaXMgYnkgY291bnRyeSwgc3RhcnRpbmcgd2l0aCBHZXJtYW55IGJlbG93LgoKCiMjRGF0YQoKUmVhZGluZyBpbiBkYXRhLiBUaGVzZSBhcmUgUERGcyBvZiByZWdpb25hbCBpbm5vdmF0aW9uIHByb2dyYW1zIHRoYXQgaGF2ZSBiZWVuIGNvbnZlcnRlZCBpbnRvIHBsYWluIHRleHQgYW5kIHRoZW4gdHJhbnNsYXRlZCBpbnRvIEVuZ2xpc2ggdXNpbmcgRUMgSlJDIHNvZnR3YXJlLiAKCmBgYHtyfQoKREFUQV9ESVIgPC0gIn4vRHJvcGJveC9SZXNlYXJjaC9FQyBKUkMgcHJvamVjdC9EYXRhL0VuZ2xpc2ggdGV4dHMvIiAKCgplY19maWxlcyA8LSByZWFkdGV4dChwYXN0ZTAoREFUQV9ESVIsICIvKiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9jdmFyc2Zyb20gPSAiZmlsZW5hbWVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGR2c2VwPSJfIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvY3Zhcm5hbWVzID0gYygiUkNvZGUiLCAiUmVnaW9uIiwgIlllYXIiLCAiTGFuZyIpKQoKZWNfZmlsZXMkY29uZGl0aW9uIDwtIGFzLm51bWVyaWMoZWNfZmlsZXMkWWVhciA+IDIwMTMpCgplY19maWxlcyRDb3VudHJ5IDwtIHdvcmQocm93Lm5hbWVzKGVjX2ZpbGVzKSwgMSwgc2VwID0gZml4ZWQoJy8nKSkKCmVjX2NvcnB1cyA8LSBjb3JwdXMoZWNfZmlsZXMsIHRleHRfZmllbGQgPSAidGV4dCIpIAoKI3N1YnNldCBvZiBjb3JwdXMgcGVyIGNvdW50cnksIGFzIGF1dG9tYXRlZCB0cmFuc2xhdGlvbiBpcyBpbXBlcmZlY3QgCiNhbmQgcGlja2luZyB1cCBsYW5ndWFnZSBzcGVjaWZpYyB0b3BpcyAKI3NvIGVzdGltYXRpb24gaXMgZG9uZSBjb3VudHJ5IGJ5IGNvdW50cnkKZGVfY29ycHVzIDwtIGNvcnB1c19zdWJzZXQoZWNfY29ycHVzLCBDb3VudHJ5PT0iR2VybWFueSIpCnBsX2NvcnB1cyA8LSBjb3JwdXNfc3Vic2V0KGVjX2NvcnB1cywgQ291bnRyeT09IlBvbGFuZCIpCnB0X2NvcnB1cyA8LSBjb3JwdXNfc3Vic2V0KGVjX2NvcnB1cywgQ291bnRyeT09IlBvcnR1Z2FsIikKY3pfY29ycHVzIDwtIGNvcnB1c19zdWJzZXQoZWNfY29ycHVzLCBDb3VudHJ5PT0iQ3plY2ggUmVwdWJsaWMiKQpgYGAKCgoKI0dlcm1hbnkKCiMjVG9rZW5pemluZyBkb2N1bWVudHMuCgpgYGB7cn0KI3Rva2VuaXppbmcKdG9rIDwtIHRva2VucyhkZV9jb3JwdXMsIHdoYXQgPSAid29yZCIsCiAgICAgICAgICAgICAgcmVtb3ZlUHVuY3QgPSBUUlVFLAogICAgICAgICAgICAgIHJlbW92ZVN5bWJvbHMgPSBUUlVFLAogICAgICAgICAgICAgIHJlbW92ZU51bWJlcnMgPSBUUlVFLAogICAgICAgICAgICAgIHJlbW92ZVR3aXR0ZXIgPSBUUlVFLAogICAgICAgICAgICAgIHJlbW92ZVVSTCA9IFRSVUUsCiAgICAgICAgICAgICAgcmVtb3ZlSHlwaGVucyA9IFRSVUUsCiAgICAgICAgICAgICAgdmVyYm9zZSA9IFRSVUUpCmBgYAoKCgoKIyNDcmVhdGluZyBkb2N1bWVudCBmZWF0dXJlIG1hdHJpeC4KCmBgYHtyfQoKZGZtIDwtIGRmbSh0b2ssIAogICAgICAgICAgIHRvbG93ZXIgPSBUUlVFLAogICAgICAgICAgIHJlbW92ZT0gYyhzdG9wd29yZHMoIlNNQVJUIiksICJtZWx0IiwgImhlc3NlbiIsICJoYW1idXJnIiwgInNjaGxlc3dpZyIsICJob2xzdGVpbiIsCiAgICAgICAgICAgICAgICAgICAgICJiYXZhcmlhIiwgImJhdmFyaWFuIiwgImJlcmxpbiIsICJicmVtZW4iLCAic2F4b25pIiwgIm5vcnRocmhpbmUiLCAid2VzdHBoYWxpYSIsCiAgICAgICAgICAgICAgICAgICAgICJyaGluZWxhbmQiLCAic2FhcmxhbmQiLCAibWVja2xlbmJ1cmciLCAid8O/cnR0ZW1iZXJnIiwgImJhZGVuIiwgImFuaGFsdCIsCiAgICAgICAgICAgICAgICAgICAgICJjaHNpc2NoZW4iLCAiY2hzaXNjaCIsICJwb21vcnNraSIsICJ6YWNob2RuaW9wb21vcnNraSIsICJrdWphd3NrbyIsICLFgsOzZMW6IiwKICAgICAgICAgICAgICAgICAgICAgInBvZGthcnBhY2tpIiwgIm1hem92aWEiLCAibWF6b3dpZWNraSIsICJwb21lcmFuaWEiLCAixZt3acSZdG9rcnp5c2tpIiwKICAgICAgICAgICAgICAgICAgICAgInBvZGxhc2tpIiwKICAgICAgICAgICAgICAgICAgICAgIndhcm1pYSIsICJsdWJ1c2tpIiwgIm1hbG9wb2xza2EiLCAibWHFgm9wb2xzayIsICJ3aWVsa29wb2xza2EiLCAic2zEhXNraWUiLAogICAgICAgICAgICAgICAgICAgICAiZHppYcWCYW8iLCAibWF6dXJpIiwgIm9sc3p0eW4iLCAixYLDs2R6a2llIiwgIm1henVyc2tpZWdvIiwgImfDs3JhIiwgInNpbGVzaWFuIiwKICAgICAgICAgICAgICAgICAgICAgIndhcnNhdyIsICJyemVzesOzdyIsICJtYXpvd3N6IiwgIm1hem93aWVja2ljaCIsICJtYcWCb3BvbHNrYSIsICJtYcWCb3BvbHNraSIsCiAgICAgICAgICAgICAgICAgICAgICLFm2zEhXNraWUiLCAia3Jha8OzdyIsICJhbGVudGVqbyIsICJ0ZWpvIiwgImxpc2JvYSIsICJhem9yIiwgImFsZ2FydiIsICJjemVjaCIsCiAgICAgICAgICAgICAgICAgICAgICJyZXB1YmwiLCAidGVqbyIsICJzb2NpZWRhZCIsICJtYWRlaXJhIiwgImxpc2JvbiIsICJzYXhvbmkiLCAiYmF2YXJpYSIsCiAgICAgICAgICAgICAgICAgICAgICJzYWNoc2VuIiksCiAgICAgICAgICAgc3RlbT1UUlVFLCAKICAgICAgICAgICB2ZXJib3NlID0gVFJVRSkKCmBgYAoKCgpgYGB7cn0KI1JlbW92aW5nIGFueSBkaWdpdHMuIGBkZm1gIHBpY2tzIHVwIGFueSBzZXBhcmF0ZWQgZGlnaXRzLCBub3QgZGlnaXRzIHRoYXQgYXJlIHBhcnQgb2YgdG9rZW5zLgpkZm0ubSA8LSBkZm1fc2VsZWN0KGRmbSwgJ1tcXGQtXScsICBzZWxlY3Rpb24gPSAicmVtb3ZlIiwgCiAgICAgICAgICAgICAgICAgICAgdmFsdWV0eXBlPSJyZWdleCIsIHZlcmJvc2UgPSBUUlVFKQoKCiNSZW1vdmluZyBhbnkgcHVuY3R1YXRpb24uIGBkZm1gIHBpY2tzIHVwIGFueSBwdW5jdHVhdGlvbiB1bmxlc3MgaXQncyBwYXJ0IG9mIGEgdG9rZW4uCmRmbS5tIDwtIGRmbV9zZWxlY3QoZGZtLm0sICJbWzpwdW5jdDpdXSIsICBzZWxlY3Rpb24gPSAicmVtb3ZlIiwgCiAgICAgICAgICAgICAgICAgICAgdmFsdWV0eXBlPSJyZWdleCIsIHZlcmJvc2UgPSBUUlVFKQoKCiNSZW1vdmluZyBhbnkgdG9rZW5zIGxlc3MgdGhhbiBmb3VyIGNoYXJhY3RlcnMuCmRmbS5tIDwtIGRmbV9zZWxlY3QoZGZtLm0sICdeLnsxLDN9JCcsICBzZWxlY3Rpb24gPSAicmVtb3ZlIiwgCiAgICAgICAgICAgICAgICAgICAgdmFsdWV0eXBlPSJyZWdleCIsIHZlcmJvc2UgPSBUUlVFKQoKYGBgCgoKYGBge3J9CiNEcm9wcGluZyB3b3JkcyB0aGF0IGFwcGVhciBsZXNzIHRoYW4gMTAgdGltZXMgYW5kIGluIGxlc3MgdGhhbiA1IGRvY3VtZW50cy4KZGZtLnRyaW0gPC0gZGZtX3RyaW0oZGZtLm0sIG1pbl9jb3VudCA9IDEwLCBtaW5fZG9jZnJlcSA9IDUpCgp0b3BmZWF0dXJlcyhkZm0udHJpbSwgbiA9IDUwKQoKc3BhcnNpdHkoZGZtLnRyaW0pCgpuZmVhdHVyZShkZm0udHJpbSkKYGBgCgoKQ29udmVydGluZyBERk0gaW50byBmb3JtYXQgZm9yIFNUTSBwYWNrYWdlCgpgYGB7cn0Kc3RtLmRmbSA8LSBjb252ZXJ0KGRmbS50cmltLCB0byA9ICJzdG0iLCAgZG9jdmFycyA9IGRvY3ZhcnMoZGVfY29ycHVzKSkKYGBgCgoKCiMjQW5hbHlzaXMKCkluIHRoZSBhbmFseXNpcyB3ZSBjb25zaWRlciB0aGUgZWZmZWN0IG9mIGludHJvZHVjaW5nIGNvbmRpdGlvbmFsaXR5IG9uIHRoZSBjb250ZW50IG9mIGlubm92YXRpb24gcHJvZ3JhbXMuIEluIG9yZGVyIHRvIGFjaGlldmUgdGhhdCB3ZSBpbXBsZW1lbnQgYSBzdHJ1Y3R1cmFsIHRvcGljIG1vZGVsIChSb2JlcnRzIGV0IGFsLiwgMjAxNSkuIFdlIG1vZGVsIHRvcGljIHByZXZhbGVuY2UgaW4gdGhlIGNvbnRleHQgb2YgdGhlIGNvbmRpdGlvbmFsaXR5IGNvbmRpdGlvbiBtYXJraW5nICBwcm9ncmFtcyBiZWZvcmUgYW5kIGFmdGVyIDIwMTMuIEluIGFkZGl0aW9uLCB3ZSBjb250cm9sIGZvciByZWdpb24gZml4ZWQgZWZmZWN0cy4gVGhlIGFpbSBpcyB0byBhbGxvdyB0aGUgb2JzZXJ2ZWQgbWV0YWRhdGEgdG8gYWZmZWN0IHRoZSBmcmVxdWVuY3kgd2l0aCB3aGljaCBhIHRvcGljIGlzIGRpc2N1c3NlZCBpbiBpbm5vdmF0aW9uIHByb2dyYW1zLiBUaGlzIGFsbG93cyB1cyB0byB0ZXN0IHRoZSBkZWdyZWUgb2YgYXNzb2NpYXRpb24gYmV0d2VlbiBjb25kaXRpb25hbGl0eSAoYW5kIHJlZ2lvbiBlZmZlY3RzKSBhbmQgdGhlIGF2ZXJhZ2UgcHJvcG9ydGlvbiBvZiBhIGRvY3VtZW50IGRpc2N1c3NpbmcgYSB0b3BpYy4gCgoKIyMjU2VhcmNoaW5nIGZvciBvcHRpbWFsIG51bWJlciBvZiB0b3BpY3MKV2UgYXNzZXNzIHRoZSBvcHRpbWFsIG51bWJlciBvZiB0b3BpY3MgdGhhdCBuZWVkIHRvIHNwZWNpZmllZCBmb3IgdGhlIFNUTSBhbmFseXNpcy4gV2UgZm9sbG93IG9yaWdpbmFsIFNUTSBwYXBlciBhbmQgZm9jdXMgb24gZXhjbHVzaXZpdHkgYW5kIHNlbWFudGljIGNvaGVyZW5jZSBtZWFzdXJlcy4gTWltbm8gZXQgYWwuICgyMDExKSBwcm9wb3NlIHNlbWFudGljIGNvaGVyZW5jZSBtZWFzdXJlLCBjbG9zZWx5IHJlbGF0ZWQgdG8gcG9pbnQtd2lzZSBtdXR1YWwgaW5mb3JtYXRpb24gbWVhc3VyZSBwcm9wb3NlZCBieSBOZXdtYW4gZXQgYWwuICgyMDEwKSB0byBldmFsdWF0ZSB0b3BpYyBxdWFsaXR5LiBNaW1ubyBldCBhbC4gKDIwMTEpIHNob3cgdGhhdCBzZW1hbnRpYyBjb2hlcmVuY2UgY29ycmVzcG9uZHMgdG8gZXhwZXJ0IGp1ZGdtZW50cyBhbmQgbW9yZSBnZW5lcmFsIGh1bWFuIGp1ZGdtZW50cyBpbiBBbWF6b24ncyBNZWNoYW5pY2FsIFR1cmsgZXhwZXJpbWVudHMuCgpFeGNsdXNpdml0eSBzY29yZSBmb3IgZWFjaCB0b3BpYyBmb2xsb3dzIEJpc2Nob2YgYW5kIEFpcm9sZGkgKDIwMTIpLiBIaWdobHkgZnJlcXVlbnQgd29yZHMgaW4gYSBnaXZlbiB0b3BpYyB0aGF0IGRvbid0IGFwcGVhciB0b28gb2Z0ZW4gaW4gb3RoZXIgdG9waWNzIGFyZSBzYWlkIHRvIG1ha2UgdGhhdCB0b3BpYyBleGNsdXNpdmUuIENvaGVzaXZlIGFuZCBleGNsdXNpdmUgdG9waWNzIGFyZSBtb3JlIHNlbWFudGljYWxseSB1c2VmdWwuIEZvbGxvd2luZyBSb2JlcnRzIGV0IGFsLiAoMjAxNSkgd2UgZ2VuZXJhdGUgYSBzZXQgb2YgY2FuZGlkYXRlIG1vZGVscyByYW5naW5nIGJldHdlZW4gMyBhbmQgNTAgdG9waWNzLiAKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpzZWFyY2ggPC0gc2VhcmNoSyhzdG0uZGZtJGRvY3VtZW50cywgc3RtLmRmbSR2b2NhYiwgSyA9IGMoMzo1MCksCiAgICAgICAgICAgICAgICAgcHJldmFsZW5jZSA9IH4gZmFjdG9yKGNvbmRpdGlvbikgKyBmYWN0b3IoUmVnaW9uKSwKICAgICAgICAgICAgICAgICAgZGF0YSA9IHN0bS5kZm0kbWV0YSkKYGBgCgoKV2UgdGhlbiBwbG90IHRoZSBleGNsdXNpdml0eSBhbmQgc2VtYW50aWMgY29oZXJlbmNlIChudW1iZXJzIGNsb3NlciB0byB6ZXJvIGluZGljYXRlIGhpZ2hlciBjb2hlcmVuY2UpLCBhbmQgc2VsZWN0IGEgbW9kZWwgb24gdGhlIHNlbWFudGljIGNvaGVyZW5jZS1leGNsdXNpdml0eSAiZnJvbnRpZXIiLCB0aGF0IGlzLCB3aGVyZSBubyBtb2RlbCBzdHJpY3RseSBkb21pbmF0ZXMgYW5vdGhlciBpbiB0ZXJtcyBvZiBzZW1hbnRpYyBjb2hlcmVuY2UgYW5kIGV4Y2x1c2l2aXR5LiAKCmBgYHtyfQojcGRmKCJzZWFyY2gucGRmIikKcGFyKG1hcj1jKDUsNCw0LDUpKy4xKQpwbG90KHNlYXJjaCRyZXN1bHRzJEssc2VhcmNoJHJlc3VsdHMkZXhjbHVzLHR5cGU9ImwiLGNvbD0icmVkIiwgCiAgICAgeGxhYj0iTnVtYmVyIG9mIHRvcGljcyIsIHlsYWI9IkV4Y2x1c2l2aXR5IikKYXhpcyhzaWRlPTEsYXQ9c2VxKDAsNTAsNSkpCiNhYmxpbmUodj1jKDUsMTApLCBjb2w9ImdyZWVuIikKcGFyKG5ldz1UUlVFKQpwbG90KHNlYXJjaCRyZXN1bHRzJEssIHNlYXJjaCRyZXN1bHRzJHNlbWNvaCwKICAgICB0eXBlPSJsIixjb2w9ImJsdWUiLHhheHQ9Im4iLHlheHQ9Im4iLHhsYWI9IiIseWxhYj0iIikKYXhpcyg0KQptdGV4dCgiU2VtYW50aWMgQ29oZXJlbmNlIixzaWRlPTQsbGluZT0zKQpsZWdlbmQoInJpZ2h0Iixjb2w9YygicmVkIiwiYmx1ZSIpLGx0eT0xLGxlZ2VuZD1jKCJleGNsIiwic2VtIGNvaCIpKQojZGV2Lm9mZigpCmBgYAoKCldlIHNlbGVjdCB0aGUgbW9kZWwgd2l0aCA3IHRvcGljcyBmb3Igb3VyIGFuYWx5c2lzIC0tIHRoZXJlJ3MgYSBkcm9wIGluIHNlbWFudGljIGNvaGVyZW5jZSBhZnRlciAkaz03JC4gV2UgZXN0aW1hdGUgdGhlIG1vZGVsIHdpdGggY29uZGl0aW9uYWxpdHkgYW5kIHJlZ2lvbiBjb3ZhcmlhdGVzLiAKCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KdG9waWNzNyA8LSBzdG0oc3RtLmRmbSRkb2N1bWVudHMsIHN0bS5kZm0kdm9jYWIsICAKICAgICAgICAgICAgIHByZXZhbGVuY2UgPSB+IGZhY3Rvcihjb25kaXRpb24pICsgZmFjdG9yKFJlZ2lvbiksIAogICAgICAgICAgICAgZGF0YSA9IHN0bS5kZm0kbWV0YSwgCiAgICAgICAgICAgICBLID0gNywgaW5pdC50eXBlID0gIlNwZWN0cmFsIikKCmBgYAoKCgojIyNFeHBsb3Jpbmcgd29yZHMgYXNzb2NpYXRlZCB3aXRoIGVhY2ggdG9waWMuCgpPbmUgd2F5IHRvIHN1bW1hcml6ZSB0b3BpY3MgaXMgdG8gY29tYmluZSB0ZXJtIGZyZXF1ZW5jeSBhbmQgZXhjbHVzaXZpdHkgdG8gdGhhdCB0b3BpYyBpbnRvIGEgdW5pdmFyaWF0ZSBzdW1tYXJ5IHN0YXRpc3RpYy4gSW4gU1RNIHBhY2thZ2UgdGhpcyBpcyBpbXBsZW1lbnRlZCBhcyBGUkVYIGZvbGxvd2luZyBCaXNjaG9mIGFuZCBBaXJvbGRpICgyMDEyKSBhbmQgQWlyb2xkaSBhbmQgQmlzY2hvZiAoMjAxNikuIFRoZSBsb2dpYyBiZWhpbmQgdGhpcyBtZWFzdXJlIGlzIHRoYXQgYm90aCBmcmVxdWVuY3kgYW5kIGV4Y2x1c2l2aXR5IGFyZSBpbXBvcnRhbnQgZmFjdG9ycyBpbiBkZXRlcm1pbmluZyBzZW1hbnRpYyBjb250ZW50IG9mIGEgd29yZCBhbmQgZm9ybSBhIHR3byBkaW1lbnNpb25hbCBzdW1tYXJ5IG9mIHRvcGljYWwgY29udGVudC4gRlJFWCBpcyB0aGUgZ2VvbWV0cmljIGF2ZXJhZ2Ugb2YgZnJlcXVlbmN5IGFuZCBleGNsdXNpdml0eSBhbmQgY2FuIGJlIHZpZXdlZCBhcyBhIHVuaXZhcmlhdGUgbWVhc3VyZSBvZiB0b3BpY2FsIGltcG9ydGFuY2UuIFNUTSBhdXRob3JzIHN1Z2dlc3QgdGhhdCBub25leGNsdXNpdmUgd29yZHMgYXJlIGxlc3MgbGlrZWx5IHRvIGNhcnJ5IHRvcGljLXNwZWNpZmljIGNvbnRlbnQsIHdoaWxlIGluZnJlcXVlbnQgd29yZHMgb2NjdXIgdG9vIHJhcmVseSB0byBmb3JtIHRoZSBzZW1hbnRpYyBjb3JlIG9mIGEgdG9waWMuIEZSRVggaXMgdGhlcmVmb3JlIGNvbWJpbmluZyBpbmZvcm1hdGlvbiBmcm9tIHRoZSBtb3N0IGZyZXF1ZW50IHdvcmRzIGluIHRoZSBjb3JwdXMgdGhhdCBhcmUgYWxzbyBsaWtlbHkgdG8gaGF2ZSBiZWVuIGdlbmVyYXRlZCBmcm9tIHRoZSB0b3BpYyBvZiBpbnRlcmVzdCB0byBzdW1tYXJpemUgaXRzIGNvbnRlbnQuIEluIHByYWN0aWNlLCB0b3BpYyBxdWFsaXR5IGlzIGFyZSB1c3VhbGx5IGV2YWx1YXRlZCBieSBoaWdoZXN0IHByb2JhYmlsaXR5IHdvcmRzLiAKCkhlcmUsIHdlIGxvb2sgYm90aCBhdCBGUkVYIGFuZCBoaWdoZXN0IHByb2JhYmlsaXR5IHdvcmRzLiAKCgpgYGB7cn0KbGFiZWxUb3BpY3ModG9waWNzNykKCmBgYAoKUGxvdHRpbmcgdGhlIHNhbWU6CgpgYGB7cn0KcGxvdCh0b3BpY3M3LHR5cGU9ImxhYmVscyIsIG4gPSAxNSwgdGV4dC5jZXggPSAuNikKCmBgYAoKCgojI0dyYXBoaWNhbCBkaXNwbGF5IG9mIGVzdGltYXRlZCB0b3BpYyBwcm9wb3J0aW9ucwoKSGVyZSB3ZSBoYXZlIGV4cGVjdGVkIHByb3BvcnRpb25zIG9mIHRoZSBjb3JwdXMgdGhhdCBiZWxvbmdzIHRvIGVhY2ggdG9waWMuCgpgYGB7cn0KcGxvdCh0b3BpY3M3LHR5cGU9InN1bW1hcnkiLCB4bGltID0gYygwLCAxKSwgbiA9IDEwLCB0ZXh0LmNleCA9IC41KQoKYGBgCgoKCgojIyBUb3BpY2FsIHBlcnNwZWN0aXZlcwoKVG9waWNzIDUgYW5kIDcgYXBwZWFyIHRvIGhhdmUgdmVyeSBzaW1pbGFyIHRvcCB3b3Jkcy4gV2UgY2FuIHBsb3QgdGhlIGNvbnRyYXN0IGluIHdvcmRzIGFjcm9zcyB0aGVzZSB0d28gdG9waWNzLiBUaGlzIHBsb3QgY2FsY3VsYXRlcyB0aGUgZGlmZmVyZW5jZSBpbiBwcm9iYWJpbGl0eSBvZiBhIHdvcmQgZm9yIHRoZSB0d28gdG9waWNzLCBub3JtYWxpemVkIGJ5IHRoZSBtYXhpbXVtIGRpZmZlcmVuY2UgaW4gcHJvYmFiaWxpdHkgb2YgYW55IHdvcmQgYmV0d2VlbiB0aGUgdHdvIHRvcGljcy4KCmBgYHtyfQpwbG90LlNUTSh0b3BpY3M3LCB0eXBlID0gInBlcnNwZWN0aXZlcyIsIHRvcGljcyA9IGMoNSw3KSkKCmBgYAoKCgoKCiMjIFdvcmRjbG91ZHMgZm9yIHRvcGljcwoKV2UgY2FuIGFsc28gbGVhcm4gbW9yZSBhYm91dCBlYWNoIHRvcGljIHdpdGggd29yZGNsb3Vkcy4gVGhlIGZpcnN0IHBsb3Qgc2hvd3MgbWFyZ2luYWwgcHJvYmFiaWxpdHkgb2Ygd29yZHMgaW4gdGhlIGNvcnB1cy4gV2UgYXJlIHBsb3R0aW5nIHRvcCAxMDAgd29yZHMuICAKCmBgYHtyfQpjbG91ZCh0b3BpY3M3LCB0b3BpYyA9IE5VTEwsIHNjYWxlID0gYygzLCAuMjUpLCBtYXgud29yZHMgPSAxMDApCmBgYAoKV29yZGNsb3VkIGZvciBUb3BpYyAxOgoKYGBge3J9CmNsb3VkKHRvcGljczcsIHRvcGljID0gMSwgc2NhbGUgPSBjKDMsIC41KSwgcmFuZG9tLm9yZGVyID0gRkFMU0Uscm90LnBlciA9IC4zLCBtYXgud29yZHMgPSAxMDApCmBgYAoKCldvcmRjbG91ZCBmb3IgVG9waWMgMjoKCmBgYHtyfQpjbG91ZCh0b3BpY3M3LCB0b3BpYyA9IDIsIHNjYWxlID0gYygzLCAuNSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLHJvdC5wZXIgPSAuMywgbWF4LndvcmRzID0gMTAwKQpgYGAKCgoKCldvcmRjbG91ZCBmb3IgVG9waWMgMzoKCmBgYHtyfQpjbG91ZCh0b3BpY3M3LCB0b3BpYyA9IDMsIHNjYWxlID0gYygzLCAuNSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLHJvdC5wZXIgPSAuMywgbWF4LndvcmRzID0gMTAwKQpgYGAKCgoKCldvcmRjbG91ZCBmb3IgVG9waWMgNDoKCmBgYHtyfQpjbG91ZCh0b3BpY3M3LCB0b3BpYyA9IDQsIHNjYWxlID0gYygzLCAuNSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLHJvdC5wZXIgPSAuMywgbWF4LndvcmRzID0gMTAwKQpgYGAKCgoKCldvcmRjbG91ZCBmb3IgVG9waWMgNToKCmBgYHtyfQpjbG91ZCh0b3BpY3M3LCB0b3BpYyA9IDUsIHNjYWxlID0gYygzLCAuNSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLHJvdC5wZXIgPSAuMywgbWF4LndvcmRzID0gMTAwKQpgYGAKCgoKCldvcmRjbG91ZCBmb3IgVG9waWMgNjoKCmBgYHtyfQpjbG91ZCh0b3BpY3M3LCB0b3BpYyA9IDYsIHNjYWxlID0gYygzLCAuNSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLHJvdC5wZXIgPSAuMywgbWF4LndvcmRzID0gMTAwKQpgYGAKCgpXb3JkY2xvdWQgZm9yIFRvcGljIDc6CgpgYGB7cn0KY2xvdWQodG9waWNzNywgdG9waWMgPSA3LCBzY2FsZSA9IGMoMywgLjUpLCByYW5kb20ub3JkZXIgPSBGQUxTRSxyb3QucGVyID0gLjMsIG1heC53b3JkcyA9IDEwMCkKYGBgCgojIyBFc3RpbWF0aW5nIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG1ldGFkYXRhIChjb25kaXRpb25hbGl0eSkgYW5kIHRvcGljIHByZXZhbGVuY2UKCldlIGxvb2sgYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRvcGljIHByb3BvcnRpb25zIGFuZCBjb25kaXRpb25hbGl0eSBmYWN0b3IuIENvbmZpZGVuY2UgaW50ZXJ2YWxzIHByb2R1Y2VkIGJ5IHRoZSBtZXRob2Qgb2YgY29tcG9zaXRpb24gaW4gU1RNIGFsbG93IHVzIHRvIHBpY2sgdXAgc3RhdGlzdGljYWwgdW5jZXJ0YWludHkgaW4gdGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLiAKCmBgYHtyfQpjb24uZWZmIDwtIGVzdGltYXRlRWZmZWN0KCB+IGZhY3Rvcihjb25kaXRpb24pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB0b3BpY3M3LCBtZXRhID0gc3RtLmRmbSRtZXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB1bmNlcnRhaW50eSA9ICJHbG9iYWwiKQoKYGBgCgpXZSBub3cgcGxvdCB0aGUgcmVzdWx0cyBvZiB0aGUgYW5hbHlzaXMgYXMgdGhlIGRpZmZlcmVuY2UgaW4gdG9waWMgcHJvcG9ydGlvbnMgZm9yIHR3byBkaWZmZXJlbnQgdmFsdWVzIG9mIGNvbmRpdGlvbmFsaXR5IChiZWZvcmUgYW5kIGFmdGVyIHRoZSBpbnRyb2R1Y3Rpb24gb2YgdGhlIHBvbGljeSkuIFBvaW50IGVzdGltYXRlcyBhbmQgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHBsb3R0ZWQuICAKCgpgYGB7cn0KcGxvdChjb24uZWZmLCBjb3ZhcmlhdGUgPSAiY29uZGl0aW9uIiwgIAogICAgIG1vZGVsID0gdG9waWNzNywgbWV0aG9kID0gImRpZmZlcmVuY2UiLCAKICAgICBjb3YudmFsdWUxID0gMSwgY292LnZhbHVlMiA9IDAsIHZlcmJvc2UubGFiZWxzID0gRkFMU0UsIHhsaW0gPSBjKC0uNSwgLjcpLAogICAgIG1haW4gPSAiRWZmZWN0IG9mIENvbmRpdGlvbmFsaXR5IikKYGBgCgpGaWd1cmUgc2hvd3MgYSB0cmVhdG1lbnQgZWZmZWN0IG9mIGNvbmRpdGlvbmFsaXR5IGludHJvZHVjdGlvbiBpbiBhbGwgc2V2ZW4gdG9waWNzLCBjb21wYXJpbmcgcHJvZ3JhbXMgYmVmb3JlIGFuZCBhZnRlciBpbnRyb2R1Y3Rpb24gb2YgY29uZGl0aW9uYWxpdHkuCgpXZSBvYnNlcnZlIHRoYXQgY29uZGl0aW9uYWxpdHkgaW50cm9kdWN0aW9uIGhhZCBhbiBlZmZlY3Qgb25seSBvbiBUb3BpYyAyLCB3aGlsZSBmb3IgdGhlIHJlbWFpbmluZyB0b3BpY3MgdGhlIGVmZmVjdCBvZiBjb25kaXRpb25hbGl0eSBpcyBub3QgZGlzdGluZ3Vpc2hhYmxlIGZyb20gemVyby4gCgpPbiBhdmVyYWdlLCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBwcm9wb3J0aW9uIG9mIHJlZ2lvbmFsIGlubm92YXRpb24gcHJvZ3JhbXMgdGhhdCBkaXNjdXNzIFRvcGljIDIgYWZ0ZXIgaW50cm9kdWN0aW9uIG9mIGNvbmRpdGlvbmFsaXR5IHJlcXVpcmVtZW50IGFuZCB0aGUgcHJvcG9ydGlvbiBvZiBwcm9ncmFtcyB0aGF0IGRpc2N1c3MgVG9waWMgMiBiZWZvcmUgY29uZGl0aW9uYWxpdHkgaW50cm9kdWN0aW9uIGlzIC4zOCAoLjE2LCAuNikuIAoKCgojIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRvcGljcwoKV2UgY2FuIGFsc28gYXNzZXNzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0b3BpY3MgaW4gdGhlIFNUTSBmcmFtZXdvcmsgdGhhdCBhbGxvd3MgY29ycmVsYXRpb25zIGJldHdlZW4gdG9waWNzLiBQb3NpdGl2ZSBjb3JyZWxhdGlvbnMgYmV0d2VlbiB0b3BpY3Mgc3VnZ2VzdCB0aGF0IGJvdGggdG9waWNzIGFyZSBsaWtlbHkgdG8gYmUgY292ZXJlZCB3aXRoaW4gYW4gaW5ub3ZhdGlvbiBwcm9ncmFtLgoKYGBge3J9CnRvcGljLmNvciA8LSB0b3BpY0NvcnIodG9waWNzNykKcGxvdC50b3BpY0NvcnIodG9waWMuY29yKQpgYGAKCkl0IGFwcGVhcnMgdGhhdCBvbmx5IFRvcGljcyAxIGFuZCA1IGFyZSBsaW5rZWQgYXQgdGhlIGRlZmF1bHQgMC4wMSBjb3JyZWxhdGlvbiBjdXRvZmYuCgoKCgoKI1BvbGFuZAoKIyNUb2tlbml6aW5nIGRvY3VtZW50cy4KCmBgYHtyfQojdG9rZW5pemluZwp0b2sgPC0gdG9rZW5zKHBsX2NvcnB1cywgd2hhdCA9ICJ3b3JkIiwKICAgICAgICAgICAgICByZW1vdmVQdW5jdCA9IFRSVUUsCiAgICAgICAgICAgICAgcmVtb3ZlU3ltYm9scyA9IFRSVUUsCiAgICAgICAgICAgICAgcmVtb3ZlTnVtYmVycyA9IFRSVUUsCiAgICAgICAgICAgICAgcmVtb3ZlVHdpdHRlciA9IFRSVUUsCiAgICAgICAgICAgICAgcmVtb3ZlVVJMID0gVFJVRSwKICAgICAgICAgICAgICByZW1vdmVIeXBoZW5zID0gVFJVRSwKICAgICAgICAgICAgICB2ZXJib3NlID0gVFJVRSkKYGBgCgoKCgojI0NyZWF0aW5nIGRvY3VtZW50IGZlYXR1cmUgbWF0cml4LgoKYGBge3J9CgpkZm0gPC0gZGZtKHRvaywgCiAgICAgICAgICAgdG9sb3dlciA9IFRSVUUsCiAgICAgICAgICAgcmVtb3ZlPSBjKHN0b3B3b3JkcygiU01BUlQiKSwgIm1lbHQiLCAiaGVzc2VuIiwgImhhbWJ1cmciLCAic2NobGVzd2lnIiwgImhvbHN0ZWluIiwKICAgICAgICAgICAgICAgICAgICAgImJhdmFyaWEiLCAiYmF2YXJpYW4iLCAiYmVybGluIiwgImJyZW1lbiIsICJzYXhvbmkiLCAibm9ydGhyaGluZSIsICJ3ZXN0cGhhbGlhIiwKICAgICAgICAgICAgICAgICAgICAgInJoaW5lbGFuZCIsICJzYWFybGFuZCIsICJtZWNrbGVuYnVyZyIsICJ3w79ydHRlbWJlcmciLCAiYmFkZW4iLCAiYW5oYWx0IiwKICAgICAgICAgICAgICAgICAgICAgImNoc2lzY2hlbiIsICJjaHNpc2NoIiwgInBvbW9yc2tpIiwgInphY2hvZG5pb3BvbW9yc2tpIiwgImt1amF3c2tvIiwgIsWCw7NkxboiLAogICAgICAgICAgICAgICAgICAgICAicG9ka2FycGFja2kiLCAibWF6b3ZpYSIsICJtYXpvd2llY2tpIiwgInBvbWVyYW5pYSIsICLFm3dpxJl0b2tyenlza2kiLAogICAgICAgICAgICAgICAgICAgICAicG9kbGFza2kiLAogICAgICAgICAgICAgICAgICAgICAid2FybWlhIiwgImx1YnVza2kiLCAibWFsb3BvbHNrYSIsICJtYcWCb3BvbHNrIiwgIndpZWxrb3BvbHNrYSIsICJzbMSFc2tpZSIsCiAgICAgICAgICAgICAgICAgICAgICJkemlhxYJhbyIsICJtYXp1cmkiLCAib2xzenR5biIsICLFgsOzZHpraWUiLCAibWF6dXJza2llZ28iLCAiZ8OzcmEiLCAic2lsZXNpYW4iLAogICAgICAgICAgICAgICAgICAgICAid2Fyc2F3IiwgInJ6ZXN6w7N3IiwgIm1hem93c3oiLCAibWF6b3dpZWNraWNoIiwgIm1hxYJvcG9sc2thIiwgIm1hxYJvcG9sc2tpIiwKICAgICAgICAgICAgICAgICAgICAgIsWbbMSFc2tpZSIsICJrcmFrw7N3IiwgImFsZW50ZWpvIiwgInRlam8iLCAibGlzYm9hIiwgImF6b3IiLCAiYWxnYXJ2IiwgImN6ZWNoIiwKICAgICAgICAgICAgICAgICAgICAgInJlcHVibCIsICJ0ZWpvIiwgInNvY2llZGFkIiwgIm1hZGVpcmEiLCAibGlzYm9uIiwgInNheG9uaSIsICJiYXZhcmlhIiwKICAgICAgICAgICAgICAgICAgICAgInNhY2hzZW4iKSwKICAgICAgICAgICBzdGVtPVRSVUUsIAogICAgICAgICAgIHZlcmJvc2UgPSBUUlVFKQoKYGBgCgoKCmBgYHtyfQojUmVtb3ZpbmcgYW55IGRpZ2l0cy4gYGRmbWAgcGlja3MgdXAgYW55IHNlcGFyYXRlZCBkaWdpdHMsIG5vdCBkaWdpdHMgdGhhdCBhcmUgcGFydCBvZiB0b2tlbnMuCmRmbS5tIDwtIGRmbV9zZWxlY3QoZGZtLCAnW1xcZC1dJywgIHNlbGVjdGlvbiA9ICJyZW1vdmUiLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXR5cGU9InJlZ2V4IiwgdmVyYm9zZSA9IFRSVUUpCgoKI1JlbW92aW5nIGFueSBwdW5jdHVhdGlvbi4gYGRmbWAgcGlja3MgdXAgYW55IHB1bmN0dWF0aW9uIHVubGVzcyBpdCdzIHBhcnQgb2YgYSB0b2tlbi4KZGZtLm0gPC0gZGZtX3NlbGVjdChkZm0ubSwgIltbOnB1bmN0Ol1dIiwgIHNlbGVjdGlvbiA9ICJyZW1vdmUiLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXR5cGU9InJlZ2V4IiwgdmVyYm9zZSA9IFRSVUUpCgoKI1JlbW92aW5nIGFueSB0b2tlbnMgbGVzcyB0aGFuIGZvdXIgY2hhcmFjdGVycy4KZGZtLm0gPC0gZGZtX3NlbGVjdChkZm0ubSwgJ14uezEsM30kJywgIHNlbGVjdGlvbiA9ICJyZW1vdmUiLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXR5cGU9InJlZ2V4IiwgdmVyYm9zZSA9IFRSVUUpCgpgYGAKCgpgYGB7cn0KI0Ryb3BwaW5nIHdvcmRzIHRoYXQgYXBwZWFyIGxlc3MgdGhhbiA1IHRpbWVzIGFuZCBpbiBsZXNzIHRoYW4gMyBkb2N1bWVudHMuCmRmbS50cmltIDwtIGRmbV90cmltKGRmbS5tLCBtaW5fY291bnQgPSA1LCBtaW5fZG9jZnJlcSA9IDMpCgp0b3BmZWF0dXJlcyhkZm0udHJpbSwgbiA9IDUwKQoKc3BhcnNpdHkoZGZtLnRyaW0pCgpuZmVhdHVyZShkZm0udHJpbSkKYGBgCgoKQ29udmVydGluZyBERk0gaW50byBmb3JtYXQgZm9yIFNUTSBwYWNrYWdlCgpgYGB7cn0Kc3RtLmRmbSA8LSBjb252ZXJ0KGRmbS50cmltLCB0byA9ICJzdG0iLCAgZG9jdmFycyA9IGRvY3ZhcnMocGxfY29ycHVzKSkKYGBgCgoKCiMjQW5hbHlzaXMKCkluIHRoZSBhbmFseXNpcyB3ZSBjb25zaWRlciB0aGUgZWZmZWN0IG9mIGludHJvZHVjaW5nIGNvbmRpdGlvbmFsaXR5IG9uIHRoZSBjb250ZW50IG9mIGlubm92YXRpb24gcHJvZ3JhbXMuIEluIG9yZGVyIHRvIGFjaGlldmUgdGhhdCB3ZSBpbXBsZW1lbnQgYSBzdHJ1Y3R1cmFsIHRvcGljIG1vZGVsIChSb2JlcnRzIGV0IGFsLiwgMjAxNSkuIFdlIG1vZGVsIHRvcGljIHByZXZhbGVuY2UgaW4gdGhlIGNvbnRleHQgb2YgdGhlIGNvbmRpdGlvbmFsaXR5IGNvbmRpdGlvbiBtYXJraW5nICBwcm9ncmFtcyBiZWZvcmUgYW5kIGFmdGVyIDIwMTMuIEluIGFkZGl0aW9uLCB3ZSBjb250cm9sIGZvciByZWdpb24gZml4ZWQgZWZmZWN0cy4gVGhlIGFpbSBpcyB0byBhbGxvdyB0aGUgb2JzZXJ2ZWQgbWV0YWRhdGEgdG8gYWZmZWN0IHRoZSBmcmVxdWVuY3kgd2l0aCB3aGljaCBhIHRvcGljIGlzIGRpc2N1c3NlZCBpbiBpbm5vdmF0aW9uIHByb2dyYW1zLiBUaGlzIGFsbG93cyB1cyB0byB0ZXN0IHRoZSBkZWdyZWUgb2YgYXNzb2NpYXRpb24gYmV0d2VlbiBjb25kaXRpb25hbGl0eSAoYW5kIHJlZ2lvbiBlZmZlY3RzKSBhbmQgdGhlIGF2ZXJhZ2UgcHJvcG9ydGlvbiBvZiBhIGRvY3VtZW50IGRpc2N1c3NpbmcgYSB0b3BpYy4gCgoKIyMjU2VhcmNoaW5nIGZvciBvcHRpbWFsIG51bWJlciBvZiB0b3BpY3MKV2UgYXNzZXNzIHRoZSBvcHRpbWFsIG51bWJlciBvZiB0b3BpY3MgdGhhdCBuZWVkIHRvIHNwZWNpZmllZCBmb3IgdGhlIFNUTSBhbmFseXNpcy4gV2UgZm9sbG93IG9yaWdpbmFsIFNUTSBwYXBlciBhbmQgZm9jdXMgb24gZXhjbHVzaXZpdHkgYW5kIHNlbWFudGljIGNvaGVyZW5jZSBtZWFzdXJlcy4gTWltbm8gZXQgYWwuICgyMDExKSBwcm9wb3NlIHNlbWFudGljIGNvaGVyZW5jZSBtZWFzdXJlLCBjbG9zZWx5IHJlbGF0ZWQgdG8gcG9pbnQtd2lzZSBtdXR1YWwgaW5mb3JtYXRpb24gbWVhc3VyZSBwcm9wb3NlZCBieSBOZXdtYW4gZXQgYWwuICgyMDEwKSB0byBldmFsdWF0ZSB0b3BpYyBxdWFsaXR5LiBNaW1ubyBldCBhbC4gKDIwMTEpIHNob3cgdGhhdCBzZW1hbnRpYyBjb2hlcmVuY2UgY29ycmVzcG9uZHMgdG8gZXhwZXJ0IGp1ZGdtZW50cyBhbmQgbW9yZSBnZW5lcmFsIGh1bWFuIGp1ZGdtZW50cyBpbiBBbWF6b24ncyBNZWNoYW5pY2FsIFR1cmsgZXhwZXJpbWVudHMuCgpFeGNsdXNpdml0eSBzY29yZSBmb3IgZWFjaCB0b3BpYyBmb2xsb3dzIEJpc2Nob2YgYW5kIEFpcm9sZGkgKDIwMTIpLiBIaWdobHkgZnJlcXVlbnQgd29yZHMgaW4gYSBnaXZlbiB0b3BpYyB0aGF0IGRvbid0IGFwcGVhciB0b28gb2Z0ZW4gaW4gb3RoZXIgdG9waWNzIGFyZSBzYWlkIHRvIG1ha2UgdGhhdCB0b3BpYyBleGNsdXNpdmUuIENvaGVzaXZlIGFuZCBleGNsdXNpdmUgdG9waWNzIGFyZSBtb3JlIHNlbWFudGljYWxseSB1c2VmdWwuIEZvbGxvd2luZyBSb2JlcnRzIGV0IGFsLiAoMjAxNSkgd2UgZ2VuZXJhdGUgYSBzZXQgb2YgY2FuZGlkYXRlIG1vZGVscyByYW5naW5nIGJldHdlZW4gMyBhbmQgNTAgdG9waWNzLiAgCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0Kc2VhcmNoIDwtIHNlYXJjaEsoc3RtLmRmbSRkb2N1bWVudHMsIHN0bS5kZm0kdm9jYWIsIEsgPSBjKDM6NTApLAogICAgICAgICAgICAgICAgIHByZXZhbGVuY2UgPSB+IGZhY3Rvcihjb25kaXRpb24pICsgZmFjdG9yKFJlZ2lvbiksCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBzdG0uZGZtJG1ldGEpCmBgYAoKCldlIHRoZW4gcGxvdCB0aGUgZXhjbHVzaXZpdHkgYW5kIHNlbWFudGljIGNvaGVyZW5jZSAobnVtYmVycyBjbG9zZXIgdG8gemVybyBpbmRpY2F0ZSBoaWdoZXIgY29oZXJlbmNlKSwgYW5kIHNlbGVjdCBhIG1vZGVsIG9uIHRoZSBzZW1hbnRpYyBjb2hlcmVuY2UtZXhjbHVzaXZpdHkgImZyb250aWVyIiwgdGhhdCBpcywgd2hlcmUgbm8gbW9kZWwgc3RyaWN0bHkgZG9taW5hdGVzIGFub3RoZXIgaW4gdGVybXMgb2Ygc2VtYW50aWMgY29oZXJlbmNlIGFuZCBleGNsdXNpdml0eS4KCmBgYHtyfQojcGRmKCJzZWFyY2gucGRmIikKcGFyKG1hcj1jKDUsNCw0LDUpKy4xKQpwbG90KHNlYXJjaCRyZXN1bHRzJEssc2VhcmNoJHJlc3VsdHMkZXhjbHVzLHR5cGU9ImwiLGNvbD0icmVkIiwgCiAgICAgeGxhYj0iTnVtYmVyIG9mIHRvcGljcyIsIHlsYWI9IkV4Y2x1c2l2aXR5IikKYXhpcyhzaWRlPTEsYXQ9c2VxKDAsNTAsNSkpCiNhYmxpbmUodj1jKDUsMTApLCBjb2w9ImdyZWVuIikKcGFyKG5ldz1UUlVFKQpwbG90KHNlYXJjaCRyZXN1bHRzJEssIHNlYXJjaCRyZXN1bHRzJHNlbWNvaCwKICAgICB0eXBlPSJsIixjb2w9ImJsdWUiLHhheHQ9Im4iLHlheHQ9Im4iLHhsYWI9IiIseWxhYj0iIikKYXhpcyg0KQptdGV4dCgiU2VtYW50aWMgQ29oZXJlbmNlIixzaWRlPTQsbGluZT0zKQpsZWdlbmQoInJpZ2h0Iixjb2w9YygicmVkIiwiYmx1ZSIpLGx0eT0xLGxlZ2VuZD1jKCJleGNsIiwic2VtIGNvaCIpKQojZGV2Lm9mZigpCmBgYAoKCldlIHNlbGVjdCB0aGUgbW9kZWwgd2l0aCA2IHRvcGljcyBmb3Igb3VyIGFuYWx5c2lzIC0tIHRoZXJlJ3MgYSBkcm9wIGluIHNlbWFudGljIGNvaGVyZW5jZSBhZnRlciAkaz02JC4gV2UgZXN0aW1hdGUgdGhlIG1vZGVsIHdpdGggY29uZGl0aW9uYWxpdHkgYW5kIHJlZ2lvbiBjb3ZhcmlhdGVzLiAKCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KdG9waWNzNiA8LSBzdG0oc3RtLmRmbSRkb2N1bWVudHMsIHN0bS5kZm0kdm9jYWIsICAKICAgICAgICAgICAgIHByZXZhbGVuY2UgPSB+IGZhY3Rvcihjb25kaXRpb24pICsgZmFjdG9yKFJlZ2lvbiksIAogICAgICAgICAgICAgZGF0YSA9IHN0bS5kZm0kbWV0YSwgCiAgICAgICAgICAgICBLID0gNiwgaW5pdC50eXBlID0gIlNwZWN0cmFsIikKCmBgYAoKCgojIyNFeHBsb3Jpbmcgd29yZHMgYXNzb2NpYXRlZCB3aXRoIGVhY2ggdG9waWMuCgpPbmUgd2F5IHRvIHN1bW1hcml6ZSB0b3BpY3MgaXMgdG8gY29tYmluZSB0ZXJtIGZyZXF1ZW5jeSBhbmQgZXhjbHVzaXZpdHkgdG8gdGhhdCB0b3BpYyBpbnRvIGEgdW5pdmFyaWF0ZSBzdW1tYXJ5IHN0YXRpc3RpYy4gSW4gU1RNIHBhY2thZ2UgdGhpcyBpcyBpbXBsZW1lbnRlZCBhcyBGUkVYIGZvbGxvd2luZyBCaXNjaG9mIGFuZCBBaXJvbGRpICgyMDEyKSBhbmQgQWlyb2xkaSBhbmQgQmlzY2hvZiAoMjAxNikuIFRoZSBsb2dpYyBiZWhpbmQgdGhpcyBtZWFzdXJlIGlzIHRoYXQgYm90aCBmcmVxdWVuY3kgYW5kIGV4Y2x1c2l2aXR5IGFyZSBpbXBvcnRhbnQgZmFjdG9ycyBpbiBkZXRlcm1pbmluZyBzZW1hbnRpYyBjb250ZW50IG9mIGEgd29yZCBhbmQgZm9ybSBhIHR3byBkaW1lbnNpb25hbCBzdW1tYXJ5IG9mIHRvcGljYWwgY29udGVudC4gRlJFWCBpcyB0aGUgZ2VvbWV0cmljIGF2ZXJhZ2Ugb2YgZnJlcXVlbmN5IGFuZCBleGNsdXNpdml0eSBhbmQgY2FuIGJlIHZpZXdlZCBhcyBhIHVuaXZhcmlhdGUgbWVhc3VyZSBvZiB0b3BpY2FsIGltcG9ydGFuY2UuIFNUTSBhdXRob3JzIHN1Z2dlc3QgdGhhdCBub25leGNsdXNpdmUgd29yZHMgYXJlIGxlc3MgbGlrZWx5IHRvIGNhcnJ5IHRvcGljLXNwZWNpZmljIGNvbnRlbnQsIHdoaWxlIGluZnJlcXVlbnQgd29yZHMgb2NjdXIgdG9vIHJhcmVseSB0byBmb3JtIHRoZSBzZW1hbnRpYyBjb3JlIG9mIGEgdG9waWMuIEZSRVggaXMgdGhlcmVmb3JlIGNvbWJpbmluZyBpbmZvcm1hdGlvbiBmcm9tIHRoZSBtb3N0IGZyZXF1ZW50IHdvcmRzIGluIHRoZSBjb3JwdXMgdGhhdCBhcmUgYWxzbyBsaWtlbHkgdG8gaGF2ZSBiZWVuIGdlbmVyYXRlZCBmcm9tIHRoZSB0b3BpYyBvZiBpbnRlcmVzdCB0byBzdW1tYXJpemUgaXRzIGNvbnRlbnQuCgoKYGBge3J9CmxhYmVsVG9waWNzKHRvcGljczYpCgpgYGAKClBsb3R0aW5nIHRoZSBzYW1lOgoKYGBge3J9CnBsb3QodG9waWNzNix0eXBlPSJsYWJlbHMiLCBuID0gMTAsIHRleHQuY2V4ID0gLjUpCgpgYGAKCgoKIyNHcmFwaGljYWwgZGlzcGxheSBvZiBlc3RpbWF0ZWQgdG9waWMgcHJvcG9ydGlvbnMKCkhlcmUgd2UgaGF2ZSBleHBlY3RlZCBwcm9wb3J0aW9ucyBvZiB0aGUgY29ycHVzIHRoYXQgYmVsb25ncyB0byBlYWNoIHRvcGljLgoKYGBge3J9CnBsb3QodG9waWNzNix0eXBlPSJzdW1tYXJ5IiwgeGxpbSA9IGMoMCwgMSksIG4gPSAxMCwgdGV4dC5jZXggPSAuNSkKCmBgYAoKCgoKIyMgVG9waWNhbCBwZXJzcGVjdGl2ZXMKClRvcGljcyA0IGFuZCAxIGFwcGVhciB0byBoYXZlIHZlcnkgc2ltaWxhciB0b3Agd29yZHMuIFdlIGNhbiBwbG90IHRoZSBjb250cmFzdCBpbiB3b3JkcyBhY3Jvc3MgdGhlc2UgdHdvIHRvcGljcy4gVGhpcyBwbG90IGNhbGN1bGF0ZXMgdGhlIGRpZmZlcmVuY2UgaW4gcHJvYmFiaWxpdHkgb2YgYSB3b3JkIGZvciB0aGUgdHdvIHRvcGljcywgbm9ybWFsaXplZCBieSB0aGUgbWF4aW11bSBkaWZmZXJlbmNlIGluIHByb2JhYmlsaXR5IG9mIGFueSB3b3JkIGJldHdlZW4gdGhlIHR3byB0b3BpY3MuCgpgYGB7cn0KcGxvdC5TVE0odG9waWNzNiwgdHlwZSA9ICJwZXJzcGVjdGl2ZXMiLCB0b3BpY3MgPSBjKDQsMSkpCgpgYGAKCgoKCgojIyBXb3JkY2xvdWRzIGZvciB0b3BpY3MKCldlIGNhbiBhbHNvIGxlYXJuIG1vcmUgYWJvdXQgZWFjaCB0b3BpYyB3aXRoIHdvcmRjbG91ZHMuIFRoZSBmaXJzdCBwbG90IHNob3dzIG1hcmdpbmFsIHByb2JhYmlsaXR5IG9mIHdvcmRzIGluIHRoZSBjb3JwdXMuIFdlIGFyZSBwbG90dGluZyB0b3AgMTAwIHdvcmRzLiAgCgpgYGB7cn0KY2xvdWQodG9waWNzNiwgdG9waWMgPSBOVUxMLCBzY2FsZSA9IGMoMiwgLjI1KSwgbWF4LndvcmRzID0gMTAwKQpgYGAKCldvcmRjbG91ZCBmb3IgVG9waWMgMToKCmBgYHtyfQpjbG91ZCh0b3BpY3M2LCB0b3BpYyA9IDEsIHNjYWxlID0gYyg0LCAuNSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLHJvdC5wZXIgPSAuMywgbWF4LndvcmRzID0gMTAwKQpgYGAKCgpXb3JkY2xvdWQgZm9yIFRvcGljIDI6CgpgYGB7cn0KY2xvdWQodG9waWNzNiwgdG9waWMgPSAyLCBzY2FsZSA9IGMoMywgLjUpLCByYW5kb20ub3JkZXIgPSBGQUxTRSxyb3QucGVyID0gLjMsIG1heC53b3JkcyA9IDEwMCkKYGBgCgoKCgpXb3JkY2xvdWQgZm9yIFRvcGljIDM6CgpgYGB7cn0KY2xvdWQodG9waWNzNiwgdG9waWMgPSAzLCBzY2FsZSA9IGMoNCwgLjUpLCByYW5kb20ub3JkZXIgPSBGQUxTRSxyb3QucGVyID0gLjMsIG1heC53b3JkcyA9IDEwMCkKYGBgCgoKCgpXb3JkY2xvdWQgZm9yIFRvcGljIDQ6CgpgYGB7cn0KY2xvdWQodG9waWNzNiwgdG9waWMgPSA0LCBzY2FsZSA9IGMoNCwgLjUpLCByYW5kb20ub3JkZXIgPSBGQUxTRSxyb3QucGVyID0gLjMsIG1heC53b3JkcyA9IDEwMCkKYGBgCgoKCgpXb3JkY2xvdWQgZm9yIFRvcGljIDU6CgpgYGB7cn0KY2xvdWQodG9waWNzNiwgdG9waWMgPSA1LCBzY2FsZSA9IGMoMywgLjUpLCByYW5kb20ub3JkZXIgPSBGQUxTRSxyb3QucGVyID0gLjMsIG1heC53b3JkcyA9IDEwMCkKYGBgCgoKCgpXb3JkY2xvdWQgZm9yIFRvcGljIDY6CgpgYGB7cn0KY2xvdWQodG9waWNzNiwgdG9waWMgPSA2LCBzY2FsZSA9IGMoMywgLjUpLCByYW5kb20ub3JkZXIgPSBGQUxTRSxyb3QucGVyID0gLjMsIG1heC53b3JkcyA9IDEwMCkKYGBgCgojIyBFc3RpbWF0aW5nIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG1ldGFkYXRhIChjb25kaXRpb25hbGl0eSkgYW5kIHRvcGljIHByZXZhbGVuY2UKCldlIGxvb2sgYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRvcGljIHByb3BvcnRpb25zIGFuZCBjb25kaXRpb25hbGl0eSBmYWN0b3IuIENvbmZpZGVuY2UgaW50ZXJ2YWxzIHByb2R1Y2VkIGJ5IHRoZSBtZXRob2Qgb2YgY29tcG9zaXRpb24gaW4gU1RNIGFsbG93IHVzIHRvIHBpY2sgdXAgc3RhdGlzdGljYWwgdW5jZXJ0YWludHkgaW4gdGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLiAKCmBgYHtyfQpjb24uZWZmIDwtIGVzdGltYXRlRWZmZWN0KCB+IGZhY3Rvcihjb25kaXRpb24pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB0b3BpY3M2LCBtZXRhID0gc3RtLmRmbSRtZXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB1bmNlcnRhaW50eSA9ICJHbG9iYWwiKQoKYGBgCgpXZSBub3cgcGxvdCB0aGUgcmVzdWx0cyBvZiB0aGUgYW5hbHlzaXMgYXMgdGhlIGRpZmZlcmVuY2UgaW4gdG9waWMgcHJvcG9ydGlvbnMgZm9yIHR3byBkaWZmZXJlbnQgdmFsdWVzIG9mIGNvbmRpdGlvbmFsaXR5IChiZWZvcmUgYW5kIGFmdGVyIHRoZSBpbnRyb2R1Y3Rpb24gb2YgdGhlIHBvbGljeSkuIFBvaW50IGVzdGltYXRlcyBhbmQgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHBsb3R0ZWQuICAKCgpgYGB7cn0KcGxvdChjb24uZWZmLCBjb3ZhcmlhdGUgPSAiY29uZGl0aW9uIiwgIAogICAgIG1vZGVsID0gdG9waWNzNiwgbWV0aG9kID0gImRpZmZlcmVuY2UiLCAKICAgICBjb3YudmFsdWUxID0gMSwgY292LnZhbHVlMiA9IDAsIHZlcmJvc2UubGFiZWxzID0gRkFMU0UsIHhsaW0gPSBjKC0xLCAxKSwKICAgICBtYWluID0gIkVmZmVjdCBvZiBDb25kaXRpb25hbGl0eSIpCmBgYAoKRmlndXJlIHNob3dzIGEgdHJlYXRtZW50IGVmZmVjdCBvZiBjb25kaXRpb25hbGl0eSBpbnRyb2R1Y3Rpb24gaW4gYWxsIHNpeCB0b3BpY3MsIGNvbXBhcmluZyBwcm9ncmFtcyBiZWZvcmUgYW5kIGFmdGVyIGludHJvZHVjdGlvbiBvZiBjb25kaXRpb25hbGl0eS4KCldlIG9ic2VydmUgdGhhdCBjb25kaXRpb25hbGl0eSBpbnRyb2R1Y3Rpb24gaGFkIGFuIGVmZmVjdCBvbiBUb3BpY3MgMiwgNCwgYW5kIDUsIHdoaWxlIGZvciB0aGUgcmVtYWluaW5nIHRvcGljcyB0aGUgZWZmZWN0IG9mIGNvbmRpdGlvbmFsaXR5IGlzIG5vdCBkaXN0aW5ndWlzaGFibGUgZnJvbSB6ZXJvLiBXaGlsZSBjb25kaXRpb25hbGl0eSBpbmNyZWFzZWQgdGhlIHVzZSBvZiBUb3BpY3MgMiBhbmQgNSwgaXQgZGVjcmVhc2VkIHRoZSB1c2Ugb2YgVG9waWMgNC4KCk9uIGF2ZXJhZ2UsIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHByb3BvcnRpb24gb2YgcmVnaW9uYWwgaW5ub3ZhdGlvbiBwcm9ncmFtcyB0aGF0IGRpc2N1c3MgVG9waWMgMiBhbmQgVG9waWMgNSBhZnRlciBpbnRyb2R1Y3Rpb24gb2YgY29uZGl0aW9uYWxpdHkgcmVxdWlyZW1lbnQgYW5kIHRoZSBwcm9wb3J0aW9uIG9mIHByb2dyYW1zIHRoYXQgZGlzY3VzcyBUb3BpY3MgMiBhbmQgNSBiZWZvcmUgY29uZGl0aW9uYWxpdHkgaW50cm9kdWN0aW9uIGlzIDAuNC4gQXQgdGhlIHNhbWUgdGltZSB0aGVyZSdzIGEgc2ltaWxhciBzY2FsZSBkZWdyZWFzZSBpbiB0aGUgZGlzY3Vzc2lvbiBvZiBUb3BpYyA0LiAgCgoKCiMjIENvcnJlbGF0aW9uIGJldHdlZW4gdG9waWNzCgpXZSBjYW4gYWxzbyBhc3Nlc3MgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRvcGljcyBpbiB0aGUgU1RNIGZyYW1ld29yayB0aGF0IGFsbG93cyBjb3JyZWxhdGlvbnMgYmV0d2VlbiB0b3BpY3MuIFBvc2l0aXZlIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIHRvcGljcyBzdWdnZXN0IHRoYXQgYm90aCB0b3BpY3MgYXJlIGxpa2VseSB0byBiZSBjb3ZlcmVkIHdpdGhpbiBhbiBpbm5vdmF0aW9uIHByb2dyYW0uCgpgYGB7cn0KdG9waWMuY29yIDwtIHRvcGljQ29ycih0b3BpY3M2KQpwbG90LnRvcGljQ29ycih0b3BpYy5jb3IpCmBgYAoKSXQgYXBwZWFycyB0aGF0IG5vbmUgb2YgdGhlIHRvcGljcyBhcmUgbGlua2VkIGF0IHRoZSBkZWZhdWx0IDAuMDEgY29ycmVsYXRpb24gY3V0b2ZmLgoKCgoKCiNQb3J0dWdhbAoKIyNUb2tlbml6aW5nIGRvY3VtZW50cy4KCmBgYHtyfQojdG9rZW5pemluZwp0b2sgPC0gdG9rZW5zKHB0X2NvcnB1cywgd2hhdCA9ICJ3b3JkIiwKICAgICAgICAgICAgICByZW1vdmVQdW5jdCA9IFRSVUUsCiAgICAgICAgICAgICAgcmVtb3ZlU3ltYm9scyA9IFRSVUUsCiAgICAgICAgICAgICAgcmVtb3ZlTnVtYmVycyA9IFRSVUUsCiAgICAgICAgICAgICAgcmVtb3ZlVHdpdHRlciA9IFRSVUUsCiAgICAgICAgICAgICAgcmVtb3ZlVVJMID0gVFJVRSwKICAgICAgICAgICAgICByZW1vdmVIeXBoZW5zID0gVFJVRSwKICAgICAgICAgICAgICB2ZXJib3NlID0gVFJVRSkKYGBgCgoKCgojI0NyZWF0aW5nIGRvY3VtZW50IGZlYXR1cmUgbWF0cml4LgoKYGBge3J9CgpkZm0gPC0gZGZtKHRvaywgCiAgICAgICAgICAgdG9sb3dlciA9IFRSVUUsCiAgICAgICAgICAgcmVtb3ZlPSBjKHN0b3B3b3JkcygiU01BUlQiKSwgIm1lbHQiLCAiaGVzc2VuIiwgImhhbWJ1cmciLCAic2NobGVzd2lnIiwgImhvbHN0ZWluIiwKICAgICAgICAgICAgICAgICAgICAgImJhdmFyaWEiLCAiYmF2YXJpYW4iLCAiYmVybGluIiwgImJyZW1lbiIsICJzYXhvbmkiLCAibm9ydGhyaGluZSIsICJ3ZXN0cGhhbGlhIiwKICAgICAgICAgICAgICAgICAgICAgInJoaW5lbGFuZCIsICJzYWFybGFuZCIsICJtZWNrbGVuYnVyZyIsICJ3w79ydHRlbWJlcmciLCAiYmFkZW4iLCAiYW5oYWx0IiwKICAgICAgICAgICAgICAgICAgICAgImNoc2lzY2hlbiIsICJjaHNpc2NoIiwgInBvbW9yc2tpIiwgInphY2hvZG5pb3BvbW9yc2tpIiwgImt1amF3c2tvIiwgIsWCw7NkxboiLAogICAgICAgICAgICAgICAgICAgICAicG9ka2FycGFja2kiLCAibWF6b3ZpYSIsICJtYXpvd2llY2tpIiwgInBvbWVyYW5pYSIsICLFm3dpxJl0b2tyenlza2kiLAogICAgICAgICAgICAgICAgICAgICAicG9kbGFza2kiLAogICAgICAgICAgICAgICAgICAgICAid2FybWlhIiwgImx1YnVza2kiLCAibWFsb3BvbHNrYSIsICJtYcWCb3BvbHNrIiwgIndpZWxrb3BvbHNrYSIsICJzbMSFc2tpZSIsCiAgICAgICAgICAgICAgICAgICAgICJkemlhxYJhbyIsICJtYXp1cmkiLCAib2xzenR5biIsICLFgsOzZHpraWUiLCAibWF6dXJza2llZ28iLCAiZ8OzcmEiLCAic2lsZXNpYW4iLAogICAgICAgICAgICAgICAgICAgICAid2Fyc2F3IiwgInJ6ZXN6w7N3IiwgIm1hem93c3oiLCAibWF6b3dpZWNraWNoIiwgIm1hxYJvcG9sc2thIiwgIm1hxYJvcG9sc2tpIiwKICAgICAgICAgICAgICAgICAgICAgIsWbbMSFc2tpZSIsICJrcmFrw7N3IiwgImFsZW50ZWpvIiwgInRlam8iLCAibGlzYm9hIiwgImF6b3IiLCAiYWxnYXJ2IiwgImN6ZWNoIiwKICAgICAgICAgICAgICAgICAgICAgInJlcHVibCIsICJ0ZWpvIiwgInNvY2llZGFkIiwgIm1hZGVpcmEiLCAibGlzYm9uIiwgInNheG9uaSIsICJiYXZhcmlhIiwKICAgICAgICAgICAgICAgICAgICAgInNhY2hzZW4iKSwKICAgICAgICAgICBzdGVtPVRSVUUsIAogICAgICAgICAgIHZlcmJvc2UgPSBUUlVFKQoKYGBgCgoKCmBgYHtyfQojUmVtb3ZpbmcgYW55IGRpZ2l0cy4gYGRmbWAgcGlja3MgdXAgYW55IHNlcGFyYXRlZCBkaWdpdHMsIG5vdCBkaWdpdHMgdGhhdCBhcmUgcGFydCBvZiB0b2tlbnMuCmRmbS5tIDwtIGRmbV9zZWxlY3QoZGZtLCAnW1xcZC1dJywgIHNlbGVjdGlvbiA9ICJyZW1vdmUiLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXR5cGU9InJlZ2V4IiwgdmVyYm9zZSA9IFRSVUUpCgoKI1JlbW92aW5nIGFueSBwdW5jdHVhdGlvbi4gYGRmbWAgcGlja3MgdXAgYW55IHB1bmN0dWF0aW9uIHVubGVzcyBpdCdzIHBhcnQgb2YgYSB0b2tlbi4KZGZtLm0gPC0gZGZtX3NlbGVjdChkZm0ubSwgIltbOnB1bmN0Ol1dIiwgIHNlbGVjdGlvbiA9ICJyZW1vdmUiLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXR5cGU9InJlZ2V4IiwgdmVyYm9zZSA9IFRSVUUpCgoKI1JlbW92aW5nIGFueSB0b2tlbnMgbGVzcyB0aGFuIGZvdXIgY2hhcmFjdGVycy4KZGZtLm0gPC0gZGZtX3NlbGVjdChkZm0ubSwgJ14uezEsM30kJywgIHNlbGVjdGlvbiA9ICJyZW1vdmUiLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXR5cGU9InJlZ2V4IiwgdmVyYm9zZSA9IFRSVUUpCgpgYGAKCgpgYGB7cn0KI0Ryb3BwaW5nIHdvcmRzIHRoYXQgYXBwZWFyIGxlc3MgdGhhbiA1IHRpbWVzIGFuZCBpbiBsZXNzIHRoYW4gMyBkb2N1bWVudHMuCmRmbS50cmltIDwtIGRmbV90cmltKGRmbS5tLCBtaW5fY291bnQgPSA1LCBtaW5fZG9jZnJlcSA9IDMpCgp0b3BmZWF0dXJlcyhkZm0udHJpbSwgbiA9IDUwKQoKc3BhcnNpdHkoZGZtLnRyaW0pCgpuZmVhdHVyZShkZm0udHJpbSkKYGBgCgoKQ29udmVydGluZyBERk0gaW50byBmb3JtYXQgZm9yIFNUTSBwYWNrYWdlCgpgYGB7cn0Kc3RtLmRmbSA8LSBjb252ZXJ0KGRmbS50cmltLCB0byA9ICJzdG0iLCAgZG9jdmFycyA9IGRvY3ZhcnMocHRfY29ycHVzKSkKYGBgCgoKCiMjQW5hbHlzaXMKCkluIHRoZSBhbmFseXNpcyB3ZSBjb25zaWRlciB0aGUgZWZmZWN0IG9mIGludHJvZHVjaW5nIGNvbmRpdGlvbmFsaXR5IG9uIHRoZSBjb250ZW50IG9mIGlubm92YXRpb24gcHJvZ3JhbXMuIEluIG9yZGVyIHRvIGFjaGlldmUgdGhhdCB3ZSBpbXBsZW1lbnQgYSBzdHJ1Y3R1cmFsIHRvcGljIG1vZGVsIChSb2JlcnRzIGV0IGFsLiwgMjAxNSkuIFdlIG1vZGVsIHRvcGljIHByZXZhbGVuY2UgaW4gdGhlIGNvbnRleHQgb2YgdGhlIGNvbmRpdGlvbmFsaXR5IGNvbmRpdGlvbiBtYXJraW5nICBwcm9ncmFtcyBiZWZvcmUgYW5kIGFmdGVyIDIwMTMuIEluIGFkZGl0aW9uLCB3ZSBjb250cm9sIGZvciByZWdpb24gZml4ZWQgZWZmZWN0cy4gVGhlIGFpbSBpcyB0byBhbGxvdyB0aGUgb2JzZXJ2ZWQgbWV0YWRhdGEgdG8gYWZmZWN0IHRoZSBmcmVxdWVuY3kgd2l0aCB3aGljaCBhIHRvcGljIGlzIGRpc2N1c3NlZCBpbiBpbm5vdmF0aW9uIHByb2dyYW1zLiBUaGlzIGFsbG93cyB1cyB0byB0ZXN0IHRoZSBkZWdyZWUgb2YgYXNzb2NpYXRpb24gYmV0d2VlbiBjb25kaXRpb25hbGl0eSAoYW5kIHJlZ2lvbiBlZmZlY3RzKSBhbmQgdGhlIGF2ZXJhZ2UgcHJvcG9ydGlvbiBvZiBhIGRvY3VtZW50IGRpc2N1c3NpbmcgYSB0b3BpYy4gCgoKIyMjU2VhcmNoaW5nIGZvciBvcHRpbWFsIG51bWJlciBvZiB0b3BpY3MKV2UgYXNzZXNzIHRoZSBvcHRpbWFsIG51bWJlciBvZiB0b3BpY3MgdGhhdCBuZWVkIHRvIHNwZWNpZmllZCBmb3IgdGhlIFNUTSBhbmFseXNpcy4gV2UgZm9sbG93IG9yaWdpbmFsIFNUTSBwYXBlciBhbmQgZm9jdXMgb24gZXhjbHVzaXZpdHkgYW5kIHNlbWFudGljIGNvaGVyZW5jZSBtZWFzdXJlcy4gTWltbm8gZXQgYWwuICgyMDExKSBwcm9wb3NlIHNlbWFudGljIGNvaGVyZW5jZSBtZWFzdXJlLCBjbG9zZWx5IHJlbGF0ZWQgdG8gcG9pbnQtd2lzZSBtdXR1YWwgaW5mb3JtYXRpb24gbWVhc3VyZSBwcm9wb3NlZCBieSBOZXdtYW4gZXQgYWwuICgyMDEwKSB0byBldmFsdWF0ZSB0b3BpYyBxdWFsaXR5LiBNaW1ubyBldCBhbC4gKDIwMTEpIHNob3cgdGhhdCBzZW1hbnRpYyBjb2hlcmVuY2UgY29ycmVzcG9uZHMgdG8gZXhwZXJ0IGp1ZGdtZW50cyBhbmQgbW9yZSBnZW5lcmFsIGh1bWFuIGp1ZGdtZW50cyBpbiBBbWF6b24ncyBNZWNoYW5pY2FsIFR1cmsgZXhwZXJpbWVudHMuCgpFeGNsdXNpdml0eSBzY29yZSBmb3IgZWFjaCB0b3BpYyBmb2xsb3dzIEJpc2Nob2YgYW5kIEFpcm9sZGkgKDIwMTIpLiBIaWdobHkgZnJlcXVlbnQgd29yZHMgaW4gYSBnaXZlbiB0b3BpYyB0aGF0IGRvbid0IGFwcGVhciB0b28gb2Z0ZW4gaW4gb3RoZXIgdG9waWNzIGFyZSBzYWlkIHRvIG1ha2UgdGhhdCB0b3BpYyBleGNsdXNpdmUuIENvaGVzaXZlIGFuZCBleGNsdXNpdmUgdG9waWNzIGFyZSBtb3JlIHNlbWFudGljYWxseSB1c2VmdWwuIEZvbGxvd2luZyBSb2JlcnRzIGV0IGFsLiAoMjAxNSkgd2UgZ2VuZXJhdGUgYSBzZXQgb2YgY2FuZGlkYXRlIG1vZGVscyByYW5naW5nIGJldHdlZW4gMyBhbmQgNTAgdG9waWNzLiAgCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0Kc2VhcmNoIDwtIHNlYXJjaEsoc3RtLmRmbSRkb2N1bWVudHMsIHN0bS5kZm0kdm9jYWIsIEsgPSBjKDM6NTApLAogICAgICAgICAgICAgICAgIHByZXZhbGVuY2UgPSB+IGZhY3Rvcihjb25kaXRpb24pICsgZmFjdG9yKFJlZ2lvbiksCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBzdG0uZGZtJG1ldGEpCmBgYAoKCldlIHRoZW4gcGxvdCB0aGUgZXhjbHVzaXZpdHkgYW5kIHNlbWFudGljIGNvaGVyZW5jZSAobnVtYmVycyBjbG9zZXIgdG8gemVybyBpbmRpY2F0ZSBoaWdoZXIgY29oZXJlbmNlKSwgYW5kIHNlbGVjdCBhIG1vZGVsIG9uIHRoZSBzZW1hbnRpYyBjb2hlcmVuY2UtZXhjbHVzaXZpdHkgImZyb250aWVyIiwgdGhhdCBpcywgd2hlcmUgbm8gbW9kZWwgc3RyaWN0bHkgZG9taW5hdGVzIGFub3RoZXIgaW4gdGVybXMgb2Ygc2VtYW50aWMgY29oZXJlbmNlIGFuZCBleGNsdXNpdml0eS4KCmBgYHtyfQojcGRmKCJzZWFyY2gucGRmIikKcGFyKG1hcj1jKDUsNCw0LDUpKy4xKQpwbG90KHNlYXJjaCRyZXN1bHRzJEssc2VhcmNoJHJlc3VsdHMkZXhjbHVzLHR5cGU9ImwiLGNvbD0icmVkIiwgCiAgICAgeGxhYj0iTnVtYmVyIG9mIHRvcGljcyIsIHlsYWI9IkV4Y2x1c2l2aXR5IikKYXhpcyhzaWRlPTEsYXQ9c2VxKDAsNTAsNSkpCiNhYmxpbmUodj1jKDUsMTApLCBjb2w9ImdyZWVuIikKcGFyKG5ldz1UUlVFKQpwbG90KHNlYXJjaCRyZXN1bHRzJEssIHNlYXJjaCRyZXN1bHRzJHNlbWNvaCwKICAgICB0eXBlPSJsIixjb2w9ImJsdWUiLHhheHQ9Im4iLHlheHQ9Im4iLHhsYWI9IiIseWxhYj0iIikKYXhpcyg0KQptdGV4dCgiU2VtYW50aWMgQ29oZXJlbmNlIixzaWRlPTQsbGluZT0zKQpsZWdlbmQoInJpZ2h0Iixjb2w9YygicmVkIiwiYmx1ZSIpLGx0eT0xLGxlZ2VuZD1jKCJleGNsIiwic2VtIGNvaCIpKQojZGV2Lm9mZigpCmBgYAoKCldlIHNlbGVjdCB0aGUgbW9kZWwgd2l0aCAxMCB0b3BpY3MgZm9yIG91ciBhbmFseXNpcyAtLSB0aGVyZSdzIG5vIGltcHJvdmVtZW50IGluIHNlbWFudGljIGNvaGVyZW5jZSBhZnRlciAkaz0xMCQuIFdlIGVzdGltYXRlIHRoZSBtb2RlbCB3aXRoIGNvbmRpdGlvbmFsaXR5IGFuZCByZWdpb24gY292YXJpYXRlcy4gCgoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CnRvcGljczEwIDwtIHN0bShzdG0uZGZtJGRvY3VtZW50cywgc3RtLmRmbSR2b2NhYiwgIAogICAgICAgICAgICAgcHJldmFsZW5jZSA9IH4gZmFjdG9yKGNvbmRpdGlvbikgKyBmYWN0b3IoUmVnaW9uKSwgCiAgICAgICAgICAgICBkYXRhID0gc3RtLmRmbSRtZXRhLCAKICAgICAgICAgICAgIEsgPSAxMCwgaW5pdC50eXBlID0gIlNwZWN0cmFsIikKCmBgYAoKCgojIyNFeHBsb3Jpbmcgd29yZHMgYXNzb2NpYXRlZCB3aXRoIGVhY2ggdG9waWMuCgpPbmUgd2F5IHRvIHN1bW1hcml6ZSB0b3BpY3MgaXMgdG8gY29tYmluZSB0ZXJtIGZyZXF1ZW5jeSBhbmQgZXhjbHVzaXZpdHkgdG8gdGhhdCB0b3BpYyBpbnRvIGEgdW5pdmFyaWF0ZSBzdW1tYXJ5IHN0YXRpc3RpYy4gSW4gU1RNIHBhY2thZ2UgdGhpcyBpcyBpbXBsZW1lbnRlZCBhcyBGUkVYIGZvbGxvd2luZyBCaXNjaG9mIGFuZCBBaXJvbGRpICgyMDEyKSBhbmQgQWlyb2xkaSBhbmQgQmlzY2hvZiAoMjAxNikuIFRoZSBsb2dpYyBiZWhpbmQgdGhpcyBtZWFzdXJlIGlzIHRoYXQgYm90aCBmcmVxdWVuY3kgYW5kIGV4Y2x1c2l2aXR5IGFyZSBpbXBvcnRhbnQgZmFjdG9ycyBpbiBkZXRlcm1pbmluZyBzZW1hbnRpYyBjb250ZW50IG9mIGEgd29yZCBhbmQgZm9ybSBhIHR3byBkaW1lbnNpb25hbCBzdW1tYXJ5IG9mIHRvcGljYWwgY29udGVudC4gRlJFWCBpcyB0aGUgZ2VvbWV0cmljIGF2ZXJhZ2Ugb2YgZnJlcXVlbmN5IGFuZCBleGNsdXNpdml0eSBhbmQgY2FuIGJlIHZpZXdlZCBhcyBhIHVuaXZhcmlhdGUgbWVhc3VyZSBvZiB0b3BpY2FsIGltcG9ydGFuY2UuIFNUTSBhdXRob3JzIHN1Z2dlc3QgdGhhdCBub25leGNsdXNpdmUgd29yZHMgYXJlIGxlc3MgbGlrZWx5IHRvIGNhcnJ5IHRvcGljLXNwZWNpZmljIGNvbnRlbnQsIHdoaWxlIGluZnJlcXVlbnQgd29yZHMgb2NjdXIgdG9vIHJhcmVseSB0byBmb3JtIHRoZSBzZW1hbnRpYyBjb3JlIG9mIGEgdG9waWMuIEZSRVggaXMgdGhlcmVmb3JlIGNvbWJpbmluZyBpbmZvcm1hdGlvbiBmcm9tIHRoZSBtb3N0IGZyZXF1ZW50IHdvcmRzIGluIHRoZSBjb3JwdXMgdGhhdCBhcmUgYWxzbyBsaWtlbHkgdG8gaGF2ZSBiZWVuIGdlbmVyYXRlZCBmcm9tIHRoZSB0b3BpYyBvZiBpbnRlcmVzdCB0byBzdW1tYXJpemUgaXRzIGNvbnRlbnQuCgoKYGBge3J9CmxhYmVsVG9waWNzKHRvcGljczEwKQoKYGBgCgpQbG90dGluZyB0aGUgc2FtZToKCmBgYHtyfQpwbG90KHRvcGljczEwLHR5cGU9ImxhYmVscyIsIG4gPSAxMCwgdGV4dC5jZXggPSAuNSkKCmBgYAoKCgojI0dyYXBoaWNhbCBkaXNwbGF5IG9mIGVzdGltYXRlZCB0b3BpYyBwcm9wb3J0aW9ucwoKSGVyZSB3ZSBoYXZlIGV4cGVjdGVkIHByb3BvcnRpb25zIG9mIHRoZSBjb3JwdXMgdGhhdCBiZWxvbmdzIHRvIGVhY2ggdG9waWMuCgpgYGB7cn0KcGxvdCh0b3BpY3MxMCx0eXBlPSJzdW1tYXJ5IiwgeGxpbSA9IGMoMCwgMSksIG4gPSAxMCwgdGV4dC5jZXggPSAuNSkKCmBgYAoKCgoKIyMgVG9waWNhbCBwZXJzcGVjdGl2ZXMKClRvcGljcyA3IGFuZCAxIGFwcGVhciB0byBoYXZlIHZlcnkgc2ltaWxhciB0b3Agd29yZHMuIFdlIGNhbiBwbG90IHRoZSBjb250cmFzdCBpbiB3b3JkcyBhY3Jvc3MgdGhlc2UgdHdvIHRvcGljcy4gVGhpcyBwbG90IGNhbGN1bGF0ZXMgdGhlIGRpZmZlcmVuY2UgaW4gcHJvYmFiaWxpdHkgb2YgYSB3b3JkIGZvciB0aGUgdHdvIHRvcGljcywgbm9ybWFsaXplZCBieSB0aGUgbWF4aW11bSBkaWZmZXJlbmNlIGluIHByb2JhYmlsaXR5IG9mIGFueSB3b3JkIGJldHdlZW4gdGhlIHR3byB0b3BpY3MuCgpgYGB7cn0KcGxvdC5TVE0odG9waWNzMTAsIHR5cGUgPSAicGVyc3BlY3RpdmVzIiwgdG9waWNzID0gYyg3LDEpKQoKYGBgCgoKCgoKIyMgV29yZGNsb3VkcyBmb3IgdG9waWNzCgpXZSBjYW4gYWxzbyBsZWFybiBtb3JlIGFib3V0IGVhY2ggdG9waWMgd2l0aCB3b3JkY2xvdWRzLiBUaGUgZmlyc3QgcGxvdCBzaG93cyBtYXJnaW5hbCBwcm9iYWJpbGl0eSBvZiB3b3JkcyBpbiB0aGUgY29ycHVzLiBXZSBhcmUgcGxvdHRpbmcgdG9wIDEwMCB3b3Jkcy4gIAoKYGBge3J9CmNsb3VkKHRvcGljczEwLCB0b3BpYyA9IE5VTEwsIHNjYWxlID0gYygyLCAuMjUpLCBtYXgud29yZHMgPSAxMDApCmBgYAoKV29yZGNsb3VkIGZvciBUb3BpYyAxOgoKYGBge3J9CmNsb3VkKHRvcGljczEwLCB0b3BpYyA9IDEsIHNjYWxlID0gYygzLCAuNSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLHJvdC5wZXIgPSAuMywgbWF4LndvcmRzID0gMTAwKQpgYGAKCgpXb3JkY2xvdWQgZm9yIFRvcGljIDI6CgpgYGB7cn0KY2xvdWQodG9waWNzMTAsIHRvcGljID0gMiwgc2NhbGUgPSBjKDMsIC41KSwgcmFuZG9tLm9yZGVyID0gRkFMU0Uscm90LnBlciA9IC4zLCBtYXgud29yZHMgPSAxMDApCmBgYAoKCgoKV29yZGNsb3VkIGZvciBUb3BpYyAzOgoKYGBge3J9CmNsb3VkKHRvcGljczEwLCB0b3BpYyA9IDMsIHNjYWxlID0gYygzLCAuNSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLHJvdC5wZXIgPSAuMywgbWF4LndvcmRzID0gMTAwKQpgYGAKCgoKCldvcmRjbG91ZCBmb3IgVG9waWMgNDoKCmBgYHtyfQpjbG91ZCh0b3BpY3MxMCwgdG9waWMgPSA0LCBzY2FsZSA9IGMoMywgLjUpLCByYW5kb20ub3JkZXIgPSBGQUxTRSxyb3QucGVyID0gLjMsIG1heC53b3JkcyA9IDEwMCkKYGBgCgoKCgpXb3JkY2xvdWQgZm9yIFRvcGljIDU6CgpgYGB7cn0KY2xvdWQodG9waWNzMTAsIHRvcGljID0gNSwgc2NhbGUgPSBjKDMsIC41KSwgcmFuZG9tLm9yZGVyID0gRkFMU0Uscm90LnBlciA9IC4zLCBtYXgud29yZHMgPSAxMDApCmBgYAoKCgoKV29yZGNsb3VkIGZvciBUb3BpYyA2OgoKYGBge3J9CmNsb3VkKHRvcGljczEwLCB0b3BpYyA9IDYsIHNjYWxlID0gYygzLCAuNSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLHJvdC5wZXIgPSAuMywgbWF4LndvcmRzID0gMTAwKQpgYGAKCgpXb3JkY2xvdWQgZm9yIFRvcGljIDc6CgpgYGB7cn0KY2xvdWQodG9waWNzMTAsIHRvcGljID0gNywgc2NhbGUgPSBjKDMsIC4xKSwgcmFuZG9tLm9yZGVyID0gRkFMU0Uscm90LnBlciA9IC4zLCBtYXgud29yZHMgPSAxMDApCmBgYAoKCldvcmRjbG91ZCBmb3IgVG9waWMgODoKCmBgYHtyfQpjbG91ZCh0b3BpY3MxMCwgdG9waWMgPSA4LCBzY2FsZSA9IGMoMywgLjMpLCByYW5kb20ub3JkZXIgPSBGQUxTRSxyb3QucGVyID0gLjMsIG1heC53b3JkcyA9IDEwMCkKYGBgCgoKV29yZGNsb3VkIGZvciBUb3BpYyA5OgoKYGBge3J9CmNsb3VkKHRvcGljczEwLCB0b3BpYyA9IDksIHNjYWxlID0gYygzLCAuNSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLHJvdC5wZXIgPSAuMywgbWF4LndvcmRzID0gMTAwKQpgYGAKCgpXb3JkY2xvdWQgZm9yIFRvcGljIDEwOgoKYGBge3J9CmNsb3VkKHRvcGljczEwLCB0b3BpYyA9IDEwLCBzY2FsZSA9IGMoMywgLjUpLCByYW5kb20ub3JkZXIgPSBGQUxTRSxyb3QucGVyID0gLjMsIG1heC53b3JkcyA9IDEwMCkKYGBgCgoKCgoKIyMgRXN0aW1hdGluZyByZWxhdGlvbnNoaXAgYmV0d2VlbiBtZXRhZGF0YSAoY29uZGl0aW9uYWxpdHkpIGFuZCB0b3BpYyBwcmV2YWxlbmNlCgpXZSBsb29rIGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0b3BpYyBwcm9wb3J0aW9ucyBhbmQgY29uZGl0aW9uYWxpdHkgZmFjdG9yLiBDb25maWRlbmNlIGludGVydmFscyBwcm9kdWNlZCBieSB0aGUgbWV0aG9kIG9mIGNvbXBvc2l0aW9uIGluIFNUTSBhbGxvdyB1cyB0byBwaWNrIHVwIHN0YXRpc3RpY2FsIHVuY2VydGFpbnR5IGluIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbC4gCgpgYGB7cn0KY29uLmVmZiA8LSBlc3RpbWF0ZUVmZmVjdCggfiBmYWN0b3IoY29uZGl0aW9uKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdG9waWNzMTAsIG1ldGEgPSBzdG0uZGZtJG1ldGEsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHVuY2VydGFpbnR5ID0gIkdsb2JhbCIpCgpgYGAKCldlIG5vdyBwbG90IHRoZSByZXN1bHRzIG9mIHRoZSBhbmFseXNpcyBhcyB0aGUgZGlmZmVyZW5jZSBpbiB0b3BpYyBwcm9wb3J0aW9ucyBmb3IgdHdvIGRpZmZlcmVudCB2YWx1ZXMgb2YgY29uZGl0aW9uYWxpdHkgKGJlZm9yZSBhbmQgYWZ0ZXIgdGhlIGludHJvZHVjdGlvbiBvZiB0aGUgcG9saWN5KS4gUG9pbnQgZXN0aW1hdGVzIGFuZCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgcGxvdHRlZC4gIAoKCmBgYHtyfQpwbG90KGNvbi5lZmYsIGNvdmFyaWF0ZSA9ICJjb25kaXRpb24iLCAgCiAgICAgbW9kZWwgPSB0b3BpY3MxMCwgbWV0aG9kID0gImRpZmZlcmVuY2UiLCAKICAgICBjb3YudmFsdWUxID0gMSwgY292LnZhbHVlMiA9IDAsIHZlcmJvc2UubGFiZWxzID0gRkFMU0UsIHhsaW0gPSBjKC0xLCAxKSwKICAgICBjaS5sZXZlbD0uOTUsCiAgICAgbWFpbiA9ICJFZmZlY3Qgb2YgQ29uZGl0aW9uYWxpdHkiKQpgYGAKCkZpZ3VyZSBzaG93cyBhIHRyZWF0bWVudCBlZmZlY3Qgb2YgY29uZGl0aW9uYWxpdHkgaW50cm9kdWN0aW9uIGluIGFsbCB0ZW4gdG9waWNzLCBjb21wYXJpbmcgcHJvZ3JhbXMgYmVmb3JlIGFuZCBhZnRlciBpbnRyb2R1Y3Rpb24gb2YgY29uZGl0aW9uYWxpdHkuCgpXZSBvYnNlcnZlIHRoYXQgY29uZGl0aW9uYWxpdHkgaW50cm9kdWN0aW9uIGhhZCBhbiBlZmZlY3Qgb24gVG9waWMgNywgd2hpbGUgZm9yIHRoZSByZW1haW5pbmcgdG9waWNzIHRoZSBlZmZlY3Qgb2YgY29uZGl0aW9uYWxpdHkgaXMgbm90IGRpc3Rpbmd1aXNoYWJsZSBmcm9tIHplcm8uIAoKT24gYXZlcmFnZSwgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcHJvcG9ydGlvbiBvZiByZWdpb25hbCBpbm5vdmF0aW9uIHByb2dyYW1zIHRoYXQgZGlzY3VzcyBUb3BpYyA3IGFmdGVyIGludHJvZHVjdGlvbiBvZiBjb25kaXRpb25hbGl0eSByZXF1aXJlbWVudCBhbmQgdGhlIHByb3BvcnRpb24gb2YgcHJvZ3JhbXMgdGhhdCBkaXNjdXNzIFRvcGljIDcgYmVmb3JlIGNvbmRpdGlvbmFsaXR5IGludHJvZHVjdGlvbiBpcyAwLjQuICAgCgoKCiMjIENvcnJlbGF0aW9uIGJldHdlZW4gdG9waWNzCgpXZSBjYW4gYWxzbyBhc3Nlc3MgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRvcGljcyBpbiB0aGUgU1RNIGZyYW1ld29yayB0aGF0IGFsbG93cyBjb3JyZWxhdGlvbnMgYmV0d2VlbiB0b3BpY3MuIFBvc2l0aXZlIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIHRvcGljcyBzdWdnZXN0IHRoYXQgYm90aCB0b3BpY3MgYXJlIGxpa2VseSB0byBiZSBjb3ZlcmVkIHdpdGhpbiBhbiBpbm5vdmF0aW9uIHByb2dyYW0uCgpgYGB7cn0KdG9waWMuY29yIDwtIHRvcGljQ29ycih0b3BpY3MxMCkKcGxvdC50b3BpY0NvcnIodG9waWMuY29yKQpgYGAKCkl0IGFwcGVhcnMgdGhhdCBUb3BpY3MgMyBhbmQgMTAgYXJlIGxpbmtlZCBhdCB0aGUgZGVmYXVsdCAwLjAxIGNvcnJlbGF0aW9uIGN1dG9mZi4KCgoKI0N6ZWNoIFJlcHVibGljCgojI1Rva2VuaXppbmcgZG9jdW1lbnRzLgoKYGBge3J9CiN0b2tlbml6aW5nCnRvayA8LSB0b2tlbnMoY3pfY29ycHVzLCB3aGF0ID0gIndvcmQiLAogICAgICAgICAgICAgIHJlbW92ZVB1bmN0ID0gVFJVRSwKICAgICAgICAgICAgICByZW1vdmVTeW1ib2xzID0gVFJVRSwKICAgICAgICAgICAgICByZW1vdmVOdW1iZXJzID0gVFJVRSwKICAgICAgICAgICAgICByZW1vdmVUd2l0dGVyID0gVFJVRSwKICAgICAgICAgICAgICByZW1vdmVVUkwgPSBUUlVFLAogICAgICAgICAgICAgIHJlbW92ZUh5cGhlbnMgPSBUUlVFLAogICAgICAgICAgICAgIHZlcmJvc2UgPSBUUlVFKQpgYGAKCgoKCiMjQ3JlYXRpbmcgZG9jdW1lbnQgZmVhdHVyZSBtYXRyaXguCgpgYGB7cn0KCmRmbSA8LSBkZm0odG9rLCAKICAgICAgICAgICB0b2xvd2VyID0gVFJVRSwKICAgICAgICAgICByZW1vdmU9IGMoc3RvcHdvcmRzKCJTTUFSVCIpLCAibWVsdCIsICJoZXNzZW4iLCAiaGFtYnVyZyIsICJzY2hsZXN3aWciLCAiaG9sc3RlaW4iLAogICAgICAgICAgICAgICAgICAgICAiYmF2YXJpYSIsICJiYXZhcmlhbiIsICJiZXJsaW4iLCAiYnJlbWVuIiwgInNheG9uaSIsICJub3J0aHJoaW5lIiwgIndlc3RwaGFsaWEiLAogICAgICAgICAgICAgICAgICAgICAicmhpbmVsYW5kIiwgInNhYXJsYW5kIiwgIm1lY2tsZW5idXJnIiwgInfDv3J0dGVtYmVyZyIsICJiYWRlbiIsICJhbmhhbHQiLAogICAgICAgICAgICAgICAgICAgICAiY2hzaXNjaGVuIiwgImNoc2lzY2giLCAicG9tb3Jza2kiLCAiemFjaG9kbmlvcG9tb3Jza2kiLCAia3VqYXdza28iLCAixYLDs2TFuiIsCiAgICAgICAgICAgICAgICAgICAgICJwb2RrYXJwYWNraSIsICJtYXpvdmlhIiwgIm1hem93aWVja2kiLCAicG9tZXJhbmlhIiwgIsWbd2nEmXRva3J6eXNraSIsCiAgICAgICAgICAgICAgICAgICAgICJwb2RsYXNraSIsICJ3YXJtaWEiLCAibHVidXNraSIsICJtYWxvcG9sc2thIiwgIm1hxYJvcG9sc2siLCAid2llbGtvcG9sc2thIiwKICAgICAgICAgICAgICAgICAgICAgInNsxIVza2llIiwgCiAgICAgICAgICAgICAgICAgICAgICJkemlhxYJhbyIsICJtYXp1cmkiLCAib2xzenR5biIsICLFgsOzZHpraWUiLCAibWF6dXJza2llZ28iLCAiZ8OzcmEiLCAic2lsZXNpYW4iLAogICAgICAgICAgICAgICAgICAgICAid2Fyc2F3IiwgInJ6ZXN6w7N3IiwgIm1hem93c3oiLCAibWF6b3dpZWNraWNoIiwgIm1hxYJvcG9sc2thIiwgIm1hxYJvcG9sc2tpIiwKICAgICAgICAgICAgICAgICAgICAgIsWbbMSFc2tpZSIsICJrcmFrw7N3IiwgImFsZW50ZWpvIiwgInRlam8iLCAibGlzYm9hIiwgImF6b3IiLCAiYWxnYXJ2IiwgImN6ZWNoIiwKICAgICAgICAgICAgICAgICAgICAgInJlcHVibCIsICJ0ZWpvIiwgInNvY2llZGFkIiwgIm1hZGVpcmEiLCAibGlzYm9uIiwgInNheG9uaSIsICJiYXZhcmlhIiwKICAgICAgICAgICAgICAgICAgICAgInNhY2hzZW4iKSwKICAgICAgICAgICBzdGVtPVRSVUUsIAogICAgICAgICAgIHZlcmJvc2UgPSBUUlVFKQoKYGBgCgoKCmBgYHtyfQojUmVtb3ZpbmcgYW55IGRpZ2l0cy4gYGRmbWAgcGlja3MgdXAgYW55IHNlcGFyYXRlZCBkaWdpdHMsIG5vdCBkaWdpdHMgdGhhdCBhcmUgcGFydCBvZiB0b2tlbnMuCmRmbS5tIDwtIGRmbV9zZWxlY3QoZGZtLCAnW1xcZC1dJywgIHNlbGVjdGlvbiA9ICJyZW1vdmUiLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXR5cGU9InJlZ2V4IiwgdmVyYm9zZSA9IFRSVUUpCgoKI1JlbW92aW5nIGFueSBwdW5jdHVhdGlvbi4gYGRmbWAgcGlja3MgdXAgYW55IHB1bmN0dWF0aW9uIHVubGVzcyBpdCdzIHBhcnQgb2YgYSB0b2tlbi4KZGZtLm0gPC0gZGZtX3NlbGVjdChkZm0ubSwgIltbOnB1bmN0Ol1dIiwgIHNlbGVjdGlvbiA9ICJyZW1vdmUiLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXR5cGU9InJlZ2V4IiwgdmVyYm9zZSA9IFRSVUUpCgoKI1JlbW92aW5nIGFueSB0b2tlbnMgbGVzcyB0aGFuIGZvdXIgY2hhcmFjdGVycy4KZGZtLm0gPC0gZGZtX3NlbGVjdChkZm0ubSwgJ14uezEsM30kJywgIHNlbGVjdGlvbiA9ICJyZW1vdmUiLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXR5cGU9InJlZ2V4IiwgdmVyYm9zZSA9IFRSVUUpCgpgYGAKCgpgYGB7cn0KI0Ryb3BwaW5nIHdvcmRzIHRoYXQgYXBwZWFyIGxlc3MgdGhhbiAyIHRpbWVzIGFuZCBpbiBsZXNzIHRoYW4gMiBkb2N1bWVudHMuCmRmbS50cmltIDwtIGRmbV90cmltKGRmbS5tLCBtaW5fY291bnQgPSAyLCBtaW5fZG9jZnJlcSA9IDIpCgp0b3BmZWF0dXJlcyhkZm0udHJpbSwgbiA9IDUwKQoKc3BhcnNpdHkoZGZtLnRyaW0pCgpuZmVhdHVyZShkZm0udHJpbSkKYGBgCgoKQ29udmVydGluZyBERk0gaW50byBmb3JtYXQgZm9yIFNUTSBwYWNrYWdlCgpgYGB7cn0Kc3RtLmRmbSA8LSBjb252ZXJ0KGRmbS50cmltLCB0byA9ICJzdG0iLCAgZG9jdmFycyA9IGRvY3ZhcnMoY3pfY29ycHVzKSkKYGBgCgoKCiMjQW5hbHlzaXMKCkluIHRoZSBhbmFseXNpcyB3ZSBjb25zaWRlciB0aGUgZWZmZWN0IG9mIGludHJvZHVjaW5nIGNvbmRpdGlvbmFsaXR5IG9uIHRoZSBjb250ZW50IG9mIGlubm92YXRpb24gcHJvZ3JhbXMuIEluIG9yZGVyIHRvIGFjaGlldmUgdGhhdCB3ZSBpbXBsZW1lbnQgYSBzdHJ1Y3R1cmFsIHRvcGljIG1vZGVsIChSb2JlcnRzIGV0IGFsLiwgMjAxNSkuIFdlIG1vZGVsIHRvcGljIHByZXZhbGVuY2UgaW4gdGhlIGNvbnRleHQgb2YgdGhlIGNvbmRpdGlvbmFsaXR5IGNvbmRpdGlvbiBtYXJraW5nICBwcm9ncmFtcyBiZWZvcmUgYW5kIGFmdGVyIDIwMTMuIEluIGNvbnRyYXN0IHRvIHRoZSBhYm92ZSBhbmFseXNpcywgd2UgZG8gbm90IGNvbnRyb2wgZm9yIHJlZ2lvbiBmaXhlZCBlZmZlY3RzIGFzIHdlIGhhdmUgb25seSBDemVjaCBuYXRpb25hbCBkb2N1bWVudHMuIFRoZSBhaW0gaXMgdG8gYWxsb3cgdGhlIG9ic2VydmVkIG1ldGFkYXRhIHRvIGFmZmVjdCB0aGUgZnJlcXVlbmN5IHdpdGggd2hpY2ggYSB0b3BpYyBpcyBkaXNjdXNzZWQgaW4gaW5ub3ZhdGlvbiBwcm9ncmFtcy4gVGhpcyBhbGxvd3MgdXMgdG8gdGVzdCB0aGUgZGVncmVlIG9mIGFzc29jaWF0aW9uIGJldHdlZW4gY29uZGl0aW9uYWxpdHkgKGFuZCByZWdpb24gZWZmZWN0cykgYW5kIHRoZSBhdmVyYWdlIHByb3BvcnRpb24gb2YgYSBkb2N1bWVudCBkaXNjdXNzaW5nIGEgdG9waWMuIAoKR2l2ZW4gdGhhdCB3ZSBoYXZlIG9ubHkgdGhyZWUgZG9jdW1lbnRzIGZvciBDWiwgd2UgY2Fubm90IHBlcmZvcm0gdGhlIHRvcGljIHNlYXJjaCBwcm9jZWR1cmVzIHdlIGltcGxlbWVudGVkIGFib3ZlLiBUbyBrZWVwIGl0IGluIGNvbnRleHQgd2Ugc2V0dGxlIGZvciB0aGUgbnVtYmVyIG9mIHRvcGljcyBzaW1pbGFyIHRvIHByZXZpb3VzIGFuYWx5c2VzIChzaXggdG9waWNzKS4KCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KdG9waWNzNiA8LSBzdG0oc3RtLmRmbSRkb2N1bWVudHMsIHN0bS5kZm0kdm9jYWIsICAKICAgICAgICAgICAgIHByZXZhbGVuY2UgPSB+IGZhY3Rvcihjb25kaXRpb24pLCAKICAgICAgICAgICAgIGRhdGEgPSBzdG0uZGZtJG1ldGEsIAogICAgICAgICAgICAgSyA9IDYsIGluaXQudHlwZSA9ICJTcGVjdHJhbCIpCgpgYGAKCgoKIyMjRXhwbG9yaW5nIHdvcmRzIGFzc29jaWF0ZWQgd2l0aCBlYWNoIHRvcGljLgoKT25lIHdheSB0byBzdW1tYXJpemUgdG9waWNzIGlzIHRvIGNvbWJpbmUgdGVybSBmcmVxdWVuY3kgYW5kIGV4Y2x1c2l2aXR5IHRvIHRoYXQgdG9waWMgaW50byBhIHVuaXZhcmlhdGUgc3VtbWFyeSBzdGF0aXN0aWMuIEluIFNUTSBwYWNrYWdlIHRoaXMgaXMgaW1wbGVtZW50ZWQgYXMgRlJFWCBmb2xsb3dpbmcgQmlzY2hvZiBhbmQgQWlyb2xkaSAoMjAxMikgYW5kIEFpcm9sZGkgYW5kIEJpc2Nob2YgKDIwMTYpLiBUaGUgbG9naWMgYmVoaW5kIHRoaXMgbWVhc3VyZSBpcyB0aGF0IGJvdGggZnJlcXVlbmN5IGFuZCBleGNsdXNpdml0eSBhcmUgaW1wb3J0YW50IGZhY3RvcnMgaW4gZGV0ZXJtaW5pbmcgc2VtYW50aWMgY29udGVudCBvZiBhIHdvcmQgYW5kIGZvcm0gYSB0d28gZGltZW5zaW9uYWwgc3VtbWFyeSBvZiB0b3BpY2FsIGNvbnRlbnQuIEZSRVggaXMgdGhlIGdlb21ldHJpYyBhdmVyYWdlIG9mIGZyZXF1ZW5jeSBhbmQgZXhjbHVzaXZpdHkgYW5kIGNhbiBiZSB2aWV3ZWQgYXMgYSB1bml2YXJpYXRlIG1lYXN1cmUgb2YgdG9waWNhbCBpbXBvcnRhbmNlLiBTVE0gYXV0aG9ycyBzdWdnZXN0IHRoYXQgbm9uZXhjbHVzaXZlIHdvcmRzIGFyZSBsZXNzIGxpa2VseSB0byBjYXJyeSB0b3BpYy1zcGVjaWZpYyBjb250ZW50LCB3aGlsZSBpbmZyZXF1ZW50IHdvcmRzIG9jY3VyIHRvbyByYXJlbHkgdG8gZm9ybSB0aGUgc2VtYW50aWMgY29yZSBvZiBhIHRvcGljLiBGUkVYIGlzIHRoZXJlZm9yZSBjb21iaW5pbmcgaW5mb3JtYXRpb24gZnJvbSB0aGUgbW9zdCBmcmVxdWVudCB3b3JkcyBpbiB0aGUgY29ycHVzIHRoYXQgYXJlIGFsc28gbGlrZWx5IHRvIGhhdmUgYmVlbiBnZW5lcmF0ZWQgZnJvbSB0aGUgdG9waWMgb2YgaW50ZXJlc3QgdG8gc3VtbWFyaXplIGl0cyBjb250ZW50LgoKCmBgYHtyfQpsYWJlbFRvcGljcyh0b3BpY3M2KQoKYGBgCgpQbG90dGluZyB0aGUgc2FtZToKCmBgYHtyfQpwbG90KHRvcGljczYsdHlwZT0ibGFiZWxzIiwgbiA9IDEwLCB0ZXh0LmNleCA9IC41KQoKYGBgCgoKCiMjR3JhcGhpY2FsIGRpc3BsYXkgb2YgZXN0aW1hdGVkIHRvcGljIHByb3BvcnRpb25zCgpIZXJlIHdlIGhhdmUgZXhwZWN0ZWQgcHJvcG9ydGlvbnMgb2YgdGhlIGNvcnB1cyB0aGF0IGJlbG9uZ3MgdG8gZWFjaCB0b3BpYy4KCmBgYHtyfQpwbG90KHRvcGljczYsdHlwZT0ic3VtbWFyeSIsIHhsaW0gPSBjKDAsIDEpLCBuID0gMTAsIHRleHQuY2V4ID0gLjUpCgpgYGAKCgoKCiMjIFRvcGljYWwgcGVyc3BlY3RpdmVzCgpUb3BpY3MgOCBhbmQgMSBhcHBlYXIgdG8gaGF2ZSB2ZXJ5IHNpbWlsYXIgdG9wIHdvcmRzLiBXZSBjYW4gcGxvdCB0aGUgY29udHJhc3QgaW4gd29yZHMgYWNyb3NzIHRoZXNlIHR3byB0b3BpY3MuIFRoaXMgcGxvdCBjYWxjdWxhdGVzIHRoZSBkaWZmZXJlbmNlIGluIHByb2JhYmlsaXR5IG9mIGEgd29yZCBmb3IgdGhlIHR3byB0b3BpY3MsIG5vcm1hbGl6ZWQgYnkgdGhlIG1heGltdW0gZGlmZmVyZW5jZSBpbiBwcm9iYWJpbGl0eSBvZiBhbnkgd29yZCBiZXR3ZWVuIHRoZSB0d28gdG9waWNzLgoKYGBge3J9CnBsb3QuU1RNKHRvcGljczYsIHR5cGUgPSAicGVyc3BlY3RpdmVzIiwgdG9waWNzID0gYygyLDMpKQoKYGBgCgoKCgoKIyMgV29yZGNsb3VkcyBmb3IgdG9waWNzCgpXZSBjYW4gYWxzbyBsZWFybiBtb3JlIGFib3V0IGVhY2ggdG9waWMgd2l0aCB3b3JkY2xvdWRzLiBUaGUgZmlyc3QgcGxvdCBzaG93cyBtYXJnaW5hbCBwcm9iYWJpbGl0eSBvZiB3b3JkcyBpbiB0aGUgY29ycHVzLiBXZSBhcmUgcGxvdHRpbmcgdG9wIDEwMCB3b3Jkcy4gIAoKYGBge3J9CmNsb3VkKHRvcGljczYsIHRvcGljID0gTlVMTCwgc2NhbGUgPSBjKDIsIC4yNSksIG1heC53b3JkcyA9IDEwMCkKYGBgCgpXb3JkY2xvdWQgZm9yIFRvcGljIDE6CgpgYGB7cn0KY2xvdWQodG9waWNzNiwgdG9waWMgPSAxLCBzY2FsZSA9IGMoMywgLjUpLCByYW5kb20ub3JkZXIgPSBGQUxTRSxyb3QucGVyID0gLjMsIG1heC53b3JkcyA9IDEwMCkKYGBgCgoKV29yZGNsb3VkIGZvciBUb3BpYyAyOgoKYGBge3J9CmNsb3VkKHRvcGljczYsIHRvcGljID0gMiwgc2NhbGUgPSBjKDMsIC4zKSwgcmFuZG9tLm9yZGVyID0gRkFMU0Uscm90LnBlciA9IC4zLCBtYXgud29yZHMgPSAxMDApCmBgYAoKCgoKV29yZGNsb3VkIGZvciBUb3BpYyAzOgoKYGBge3J9CmNsb3VkKHRvcGljczYsIHRvcGljID0gMywgc2NhbGUgPSBjKDMsIC41KSwgcmFuZG9tLm9yZGVyID0gRkFMU0Uscm90LnBlciA9IC4zLCBtYXgud29yZHMgPSAxMDApCmBgYAoKCgoKV29yZGNsb3VkIGZvciBUb3BpYyA0OgoKYGBge3J9CmNsb3VkKHRvcGljczYsIHRvcGljID0gNCwgc2NhbGUgPSBjKDMsIC41KSwgcmFuZG9tLm9yZGVyID0gRkFMU0Uscm90LnBlciA9IC4zLCBtYXgud29yZHMgPSAxMDApCmBgYAoKCgoKV29yZGNsb3VkIGZvciBUb3BpYyA1OgoKYGBge3J9CmNsb3VkKHRvcGljczYsIHRvcGljID0gNSwgc2NhbGUgPSBjKDMsIC41KSwgcmFuZG9tLm9yZGVyID0gRkFMU0Uscm90LnBlciA9IC4zLCBtYXgud29yZHMgPSAxMDApCmBgYAoKCgoKV29yZGNsb3VkIGZvciBUb3BpYyA2OgoKYGBge3J9CmNsb3VkKHRvcGljczYsIHRvcGljID0gNiwgc2NhbGUgPSBjKDMsIC41KSwgcmFuZG9tLm9yZGVyID0gRkFMU0Uscm90LnBlciA9IC4zLCBtYXgud29yZHMgPSAxMDApCmBgYAoKCgoKCiMjIEVzdGltYXRpbmcgcmVsYXRpb25zaGlwIGJldHdlZW4gbWV0YWRhdGEgKGNvbmRpdGlvbmFsaXR5KSBhbmQgdG9waWMgcHJldmFsZW5jZQoKV2UgbG9vayBhdCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdG9waWMgcHJvcG9ydGlvbnMgYW5kIGNvbmRpdGlvbmFsaXR5IGZhY3Rvci4gQ29uZmlkZW5jZSBpbnRlcnZhbHMgcHJvZHVjZWQgYnkgdGhlIG1ldGhvZCBvZiBjb21wb3NpdGlvbiBpbiBTVE0gYWxsb3cgdXMgdG8gcGljayB1cCBzdGF0aXN0aWNhbCB1bmNlcnRhaW50eSBpbiB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwuIAoKYGBge3J9CmNvbi5lZmYgPC0gZXN0aW1hdGVFZmZlY3QoIH4gZmFjdG9yKGNvbmRpdGlvbiksIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRvcGljczYsIG1ldGEgPSBzdG0uZGZtJG1ldGEsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHVuY2VydGFpbnR5ID0gIkdsb2JhbCIpCgpgYGAKCldlIG5vdyBwbG90IHRoZSByZXN1bHRzIG9mIHRoZSBhbmFseXNpcyBhcyB0aGUgZGlmZmVyZW5jZSBpbiB0b3BpYyBwcm9wb3J0aW9ucyBmb3IgdHdvIGRpZmZlcmVudCB2YWx1ZXMgb2YgY29uZGl0aW9uYWxpdHkgKGJlZm9yZSBhbmQgYWZ0ZXIgdGhlIGludHJvZHVjdGlvbiBvZiB0aGUgcG9saWN5KS4gUG9pbnQgZXN0aW1hdGVzIGFuZCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgcGxvdHRlZC4gIAoKCmBgYHtyfQpwbG90KGNvbi5lZmYsIGNvdmFyaWF0ZSA9ICJjb25kaXRpb24iLCAgCiAgICAgbW9kZWwgPSB0b3BpY3M2LCBtZXRob2QgPSAiZGlmZmVyZW5jZSIsIAogICAgIGNvdi52YWx1ZTEgPSAxLCBjb3YudmFsdWUyID0gMCwgdmVyYm9zZS5sYWJlbHMgPSBGQUxTRSwgeGxpbSA9IGMoLTEsIDEpLAogICAgIGNpLmxldmVsPS45NSwKICAgICBtYWluID0gIkVmZmVjdCBvZiBDb25kaXRpb25hbGl0eSIpCmBgYAoKRmlndXJlIHNob3dzIGEgdHJlYXRtZW50IGVmZmVjdCBvZiBjb25kaXRpb25hbGl0eSBpbnRyb2R1Y3Rpb24gaW4gYWxsIHNpeCB0b3BpY3MsIGNvbXBhcmluZyBwcm9ncmFtcyBiZWZvcmUgYW5kIGFmdGVyIGludHJvZHVjdGlvbiBvZiBjb25kaXRpb25hbGl0eS4KCldlIG9ic2VydmUgdGhhdCBjb25kaXRpb25hbGl0eSBpbnRyb2R1Y3Rpb24gaGFkIGFuIGVmZmVjdCBvbiBUb3BpYyAzLCB3aGlsZSBmb3IgdGhlIHJlbWFpbmluZyB0b3BpY3MgdGhlIGVmZmVjdCBvZiBjb25kaXRpb25hbGl0eSBpcyBub3QgZGlzdGluZ3Vpc2hhYmxlIGZyb20gemVyby4gCgpPbiBhdmVyYWdlLCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBwcm9wb3J0aW9uIG9mIHJlZ2lvbmFsIGlubm92YXRpb24gcHJvZ3JhbXMgdGhhdCBkaXNjdXNzIFRvcGljIDMgYWZ0ZXIgaW50cm9kdWN0aW9uIG9mIGNvbmRpdGlvbmFsaXR5IHJlcXVpcmVtZW50IGFuZCB0aGUgcHJvcG9ydGlvbiBvZiBwcm9ncmFtcyB0aGF0IGRpc2N1c3MgVG9waWMgMyBiZWZvcmUgY29uZGl0aW9uYWxpdHkgaW50cm9kdWN0aW9uIGlzIDAuOC4gICAKCgoKIyMgQ29ycmVsYXRpb24gYmV0d2VlbiB0b3BpY3MKCldlIGNhbiBhbHNvIGFzc2VzcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdG9waWNzIGluIHRoZSBTVE0gZnJhbWV3b3JrIHRoYXQgYWxsb3dzIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIHRvcGljcy4gUG9zaXRpdmUgY29ycmVsYXRpb25zIGJldHdlZW4gdG9waWNzIHN1Z2dlc3QgdGhhdCBib3RoIHRvcGljcyBhcmUgbGlrZWx5IHRvIGJlIGNvdmVyZWQgd2l0aGluIGFuIGlubm92YXRpb24gcHJvZ3JhbS4KCmBgYHtyfQp0b3BpYy5jb3IgPC0gdG9waWNDb3JyKHRvcGljczYpCnBsb3QudG9waWNDb3JyKHRvcGljLmNvcikKYGBgCgpJdCBhcHBlYXJzIHRoYXQgYWxsIHRvcGljcyBhcGFydCBmcm9tIFRvcGljIDIgYXJlIGxpbmtlZCBhdCB0aGUgZGVmYXVsdCAwLjAxIGNvcnJlbGF0aW9uIGN1dG9mZi4KCgo=